Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

next.js 源码相关 #368

Open
cisen opened this issue Apr 8, 2019 · 0 comments
Open

next.js 源码相关 #368

cisen opened this issue Apr 8, 2019 · 0 comments

Comments

@cisen
Copy link
Owner

cisen commented Apr 8, 2019

整体总结

v1.0.0 总结

  • next实现参考了:https://github.com/facebookarchive/react-page
  • 文章参考:https://rauchg.com/2014/7-principles-of-rich-web-applications/
  • https://github.com/cisen/sourcecode-nextjs-1.0.0
  • next很重要的一点是实现了异步加载组件,过程是
    • 前端,location.href改变,App的componentWillReceiveProps监听到,调用router执行所有侦听者
    • 前端,router监听到路由变更,通过xmlhttprequest异步加载组件字符串
    • 后端,收到路由请求,匹配到'/:path+.json', 加载.next\bundles\pages目录下面对应的文件字符串
    • 后端,将字符串组成json返回给前端
    • 前端,再使用eval函数执行得到组件信息
    • 前端,得到的组件信息更新到app的state
  • next还有一个作用,实现返回整个页面的字符串
  • 所以所谓的ssr就是路由解析,然后分块加载字符串模板

问答

next做了什么?

  • server
    • 解析命令参数
    • 初始化路由map,创建httpServer
    • 插入路由配置到路由map,然后如果路由匹配成功就会使用react的服务端render生成html字符串
    • 执行start,开始侦听端口,使用webpack hotloader侦听文件变更

client是如何引入?

  • client目录下会被打包
  • 然后会在lib\document.js模板里面引入
  • 然后在server\render.js里引入document.js模板,并且使用createElement填充

client做了什么?

  • 使用eval从window.__NEXT_DATA__全局变量中获取app和component组件
  • 实例化一个lib/router组件,通过window.location.href加载对应的组件
  • 将router对象传给App组件存储到state中。app收到prop变更的时候会调用propsToState,然后使用router调用所有侦听者。者其实也是路由侦听过程。
  • 获取__next id的dom,然后插入router返回的组件

lib做了什么?

  • 提供一个App组件
    • 这个组件同步路由参数到state
  • 提供一个router类
    • 该类用set对象实现一个发布订阅
    • 该类使用async和promise,xmlHttpRequest,根据路由请求后端获取组件的字符串数据
    • 使用eval执行字符串代码得到组件实例和props
    • 使用props触发所有的订阅者
  • 提供一个document模板
    • 该模板会实现一个load方法(创建script标签),引入next的client.js
    • 插入一个__next为id的dom,里面可以插入一段html

next的webpack做了什么?

  • 添加next的cssalias
  • hotloader功能
  • 清理文件夹

v9.0.0总结

next-server

  • 基本原理没变,甚至基础路由也是:packages\next-server\server\next-server.tsgenerateRoutes方法,匹配路由,通过render生成html字符串返回

next

  • 多了预加载js,预加载css。在packages\next\pages\_document.tsx里面的比如:getPreloadMainLinks
  • 加载页面有点不同
    • 以前是使用你ajax加载的
    • 现在是使用生成script标签,具体在packages\next\client\page-loader.js的loadPage方法。还会有一个自己的pageCache页面缓存。加载完成后使用下面的方法执行js代码。
    • 现在还通过webpack的注入代码加载后的执行window.__NEXT_P.push函数:packages\next\build\webpack\loaders\next-client-pages-loader.ts
    • 这里注意,window.__NEXT_P.push方法被重写了window.__NEXT_P.push = register,也就是说调用push的时候,其实就完成了异步加载页面的注册和执行
    • 这里还会存储到pageCache缓存中
    • 注册完成后就会触发pageRegisterEvents事件模型,触发页面刷新
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant