next.js 的服务端渲染机制(一)

前后端同构,作为针对单页应用 SEO 优化乏力、首屏速度瓶颈等问题而产出的解决方案,近来在 react、vue 等前端技术栈中都得到了支持。当我们正打算抛弃传统的纯服务端渲染模式,拥抱前后端分离的最佳实践时,有些人却已经从单页应用的格局里跳出,重新去思考和定义服务端渲染。

前后端同构是指在前后端维护同一份代码。它是在SPA的基础上,利用服务端渲染(SSR)直出首屏,解除单页面应用(SPA)在首屏渲染上面临的窘境。明确地说,同构是将传统的纯服务端直出的首屏优势和SPA的站内体验优势结合起来,以取得最优解的解决方案。

两种渲染方式

next.js 是基于 react 的优秀的同构直出方案,结合 webpack 和自身提供的路由机制,可以说是开箱即用。近期由于项目技术栈迁移,接触到了 next,顺便也把 next 的源码看了一遍,所以抽空记一记。对 next 或者同构不太了解的建议先移步 next.js。next 的核心代码在于定制了一套 react 的服务端渲染方案,所以以下也是按照这个流程分步剖析源码。

目录结构一览
next 源码 server 目录

next 源码 lib 目录

next 服务端渲染的核心代码位于 server 目录下,完成了请求监听、路由分发、组件渲染和请求回馈等多个环节,lib 中的模块一部分是 next 自身使用(如app.js),另一部分是暴露给开发者的可用模块(如dynamic.js)。

如何启动服务

next 提供了它自己的 CLI,开发模式下我们直接通过 nextnext dev 执行 bin 目录下的 bin/next脚本。它通过你传入的参数去判别不同的操作,然后分发执行同目录下对应的其他脚本,当我们执行next时,bin/next会对应执行bin/next-dev

next 源码 bin 目录

bin/next-dev中,根据代码我们可以猜想 next 完成了一个关键的操作:实例化一个服务对象,然后启动监听 http 请求。而同样的,在 bin/next-start中我们也能看到相同的代码。

bin / next-dev
document 请求时,如何完成服务端渲染

注意到启动服务时引入的的模块server/index.js,我们发现这个模块 export 了一个拥有许多方法的丰富的 server 类,不难意识到就是这个类完成了大部分的渲染工作。实际上不仅如此,这个 server 类兼具组件渲染、路由匹配、错误机制、缓存处理等等多个环节的实现,服务端的核心功能都浓缩在这个类上。

server / index.js

而在 bin/next-dev执行的start()方法中,this.prepare()会根据实例化 server 对象传入的dev字段来判断是否启动hot-reloader,这个不做深入。关键的,我们可以看到之前的猜测是正确的,这里 next 利用node原生内置的http模块启动了一个服务,并传入了监听的回调函数。

server / index.js

追溯这个回调函数的本体,我们定位到handleRequest这个函数,它首先对请求的 Url 做了一层处理,然后调用了run()方法,并将处理后的参数传了进去。

server / index.js

而在run()方法里边,除了根据 dev 去运行hot-reloader和错误处理之外,next 做了一个路由的匹配。那么这个路由又是哪来的呢?
server / index.js

基于 page 目录路径的路由匹配是如何实现的

定位一下不难发现,在实例化 server 对象(construtor())的时候,next 调用了它的defineRoutes()方法,在这个方法中定义了一个 routes 对象。这个对象是一系列路由和回调函数的映射。

server / index.js

而定义这个对象后,next 又为这个对象增加多一个路由处理,并且将这个映射集合一并添加到this.router上。增加的这个路由实际上就是我们的页面 URL 匹配(划重点,这里是页面请求的入口),而this.router是 next 自身实现的路由器,这里只是做一个简单的路由登记。
server / index.js

看回run()方法,正是服务启动时做了路由登记,在这里才能执行路由查询,并且执行了相应的回调。当然如果不存在回调,说明 URL 无效,自然是返回404咯。
server / index.js

为了弄清楚 URL 的 path 是如何对应到文件路径,我们继续深入。看回刚刚我划了重点的地方,我们可以看到页面请求时执行的回调中,调用了一个 render()方法。在其中,next 除了一些常规的错误处理之外,最重要的是:1、调用了renderToHTML()方法; 2、调用了sendHTML()函数。可想而知这个步骤分别完成了页面渲染和请求回馈两个环节,而追溯这两个函数,可以定位到都来自于同目录下的server/render.js模块。

image.png

未完,后续请看 next.js 的服务端渲染机制(二)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,598评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,468评论 25 707
  • react+redux+webpack+babel+npm+shell+git这方面的内容我会随时更新,更新内容放...
    liangklfang阅读 648评论 0 1
  • 那一刻你哭了 是地动天裂的哭 哭着不再相见 何为再见 就是昨夜相拥 黎明却是天堂与模糊的视线 我在撕心裂肺的哭泣 ...
    筱河_ebcf阅读 199评论 0 1
  • Lulus阅读 1,297评论 0 0