Next.js源码解析——启动入口篇
前言
Next.js作为一款优秀的React同构框架,开箱即用的特点和社区生态完整一直给我的感觉就是用起来很香,上线了更香,npm上weekly donwload目前已超40万,并有逐渐上涨的趋势,不信看下图
命令行入口
一般来说想研究一个框架的源码但又不知道从何入手的话,从命令行启动开始入手是一个不错的选择,因为不管上层封装如何复杂,最终的结果都是由命令行去执行,所以可以把命令行当成一个入口自底向上进行抽丝剥茧的反向剖析框架运行过程。
先来看一下next
的项目结构
可以看到packages
目录下有5个文件夹:
create-next-app
:next脚手架next
: next.js,也就框架本身next-bundle-analyze
: 打包分析插件,类似于webpack-bundile-analyzernext-mdx
: mdx.js插件,用jsx写markdown(没用过,有兴趣的可以去看看,不是本文重点)next-server
: next.js服务端配置,同构框架的实现核心
所以文章只会重点对next
和next-server
进行探索,其他都是配套基建在此就不讲述了。
按照官方文档给出的命令行配置,如下图:
再点开next
文件夹,就可以看到cli
中对应的对应的文件:
没错,就是你了!
启动机制
找到对应的入口后,下面就开始分析next
启动机制是怎样的,这里的启动机制主要包括:
- 处理文件请求(handle request)
- 匹配约定式路由(match router)
- 发送node渲染后的html模版(render to html)
以命令行next start
为例,因为dev
和prod
环境在配置上会有一定的差别,这种差别一般都是在开发环境中要开启比如dev-server
、HMR
、编译到内存硬盘等配置,并不是同构渲染逻辑的核心,所以从轻就简直接去看next-start.ts
是怎么运作的。
next-start.ts
在next-start
中的核心是一个叫startServer
的方法,然后返回一个promise
后执行app.prepare
,那就先去看一下startServer
是个什么东西。
start-server.ts
继续抓重点,这里的重点是下面这两个两个:
const app = next(serverOptions)
const srv = http.createServer(app.getRequestHandler())
看到这里可能会有点懵逼,难道next
实例化后调用它的getRequestHandler
方法传到http服务同构渲染的过程就完了吗?先不慌,让我来简单解释下同构渲染的流程:
- 1.前端代码经过生产/开发编译打包后存放到对应路径/内存硬盘中
- 2.服务端读取打包文件,调用前端提供的渲染方法(比如react提供的
renderToString
)渲染成字符串,并进行注水等操作,同时把打包后的文件挂载到模版上 - 3.最后把注水完成的模版字符串通过
res.end
返回,返回后就是服务端渲染的效果
所以,app.getRequestHandler
是next
一个专门提供给http.createServer
服务的callback
,这个cb
意义就是通过浏览器请求路由去读取对应的打包文件,然后渲染对应的模版字符串,最后返回res.end(html)
完成同构渲染,因此getRequestHandler
也可以看作是next
启动真正意义上的入口。
再来看看getRequestHandler
做了那些哪些事情
next-server.ts
在next-server.ts
中getRequestHandler
返回私有方法handleRequest
,handleRequest
接收http服务的request
和response
,以及一个可选参数parseUrl
,如果没有传进来那就把req.url
传入url
(node.js自带的模块)的parse
进行解析,可能会有疑问🤔️,解析这个东西有啥用。
简单的说主要解析出protocol
(网络协议)、host
(主机) port
(端口),pathname
(路径),query
(参数),重要的大概就是这些,其他就不再列举了,前面提到过next
会根据路径去匹配路由(也是看了波源码才知道原来约定式路由原来就这么简单吗?!),这个时候就需要用到pathname
和query
去匹配。
再往下看解析url后走到了执行run
方法,看来run
是核心中的核心啊,再去看看这是个什么东西
Bingo!到这里看到了this.router.match
,这不就对应了上面简单总结的同构渲染流程第二步上了吗,先匹配路由再渲染模版。
OK!到这里Next.js的启动机制就已基本解析完成了,完结,撒花🎉🎉🎉。