ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Next.js 源码走读:一次 build、一个请求、热更新,框架内部到底发生了什么

Next.js 源码走读:一次 build、一个请求、热更新,框架内部到底发生了什么 Next.js 源码走读一次 build、一个请求、热更新框架内部到底发生了什么【免费下载链接】next.jsThe React Framework项目地址: https://gitcode.com/GitHub_Trending/next/next.js如果你改了一行样式npm run dev页面闪一下就生效了但next build却要重新跑好几分钟——为什么开发态和构建态差这么多这是新手读 Next.js 源码时最常见的困惑。本文按一条请求的生命周期走读它的三个核心部分构建期如何从代码产出.next目录请求期NextServer如何把一次 HTTP 请求派发到具体路由模块开发期热更新为什么能做到秒级响应。构建产物从哪里来先记住一句话构建期做的事就是发现所有路由 决定每个路由怎么打包 生成一份份清单文件。入口在 packages/next/src/build/index.ts 的build()函数它按 trace span 组织出清晰的阶段加载.env→ 加载next.configPHASE_PRODUCTION_BUILD阶段→ 路由发现 → 编译 → 静态生成。路由发现由route-discovery.ts里的discoverRoutes完成把你的app/和pages/目录扫成一张路由映射表——文件系统即路由落到代码里就是这一步。编译分两条路Turbopack现在默认和 Webpacksrc/build/webpack-config.ts 及webpack/下的 loaders、plugins外部依赖通过handle-externals.ts剔除出 bundle。最后写出一堆 manifestbuild-manifest、routes-manifest、prerender-manifest 等放进.next目录运行时全靠读它们工作。构建入口的代码结构能直观看到这种分阶段 可观测的写法const nextBuildSpan trace(next-build, undefined, { buildMode, version }) await nextBuildSpan.traceAsyncFn(async () { const { loadedEnvFiles } nextBuildSpan .traceChild(load-dotenv).traceFn(() loadEnvConfig(dir, false, Log)) const config await nextBuildSpan .traceChild(load-next-config).traceAsyncFn(() loadConfig(PHASE_PRODUCTION_BUILD, dir, {...})) })一个请求的完整走位结论请求先进管道再匹配路由最后交给具体的路由模块渲染全程不直接碰你的页面代码。HTTP 入口是 packages/next/src/server/ 下的NextServernext.ts 中的类它继承自base-server.ts的基类负责接收请求、解析 URL。接着依次是执行中间件/Proxy → 按路由规则匹配静态路由优先于动态路由→ 命中route-modules/下对应类型的模块app-page、app-route、pages、pages-api每种路由一个模块互不干扰。模块内部才做组件加载load-components.ts和渲染render.tsx支持 SSR、SSG 两种产物形态能直接读磁盘上的预渲染 HTML 的就读省掉整个 React 渲染。响应缓存和 revalidate 机制也挂在这一层命中响应缓存的请求根本不会触发渲染。热重载为什么这么快回到开头的困惑答案就藏在这里开发服务器是按需编译只编译你当前访问的页面而 build 是全量编译。开发入口是 packages/next/src/server/dev/next-dev-server.ts它包在NextServer外面多了一层开发态逻辑。文件变更由hot-reloader-webpack.ts/hot-reloader-turbopack.ts监听对应你选择的 bundler改动后通过hot-middleware.ts推 HMR 消息到浏览器未失效的模块直接复用缓存。on-demand-entry-handler.ts负责把这次编译哪些入口精确到当前请求的页面——所以开发时改哪页编哪页而next build会把所有页面都预编译一遍这就是两者速度差异的根本原因。开发态还额外跑类型检查、source map 还原、浏览器日志转发browser-logs/这些在生产态全部不存在。三条可以带走的设计经验构建期和运行期之间用 manifest 文件做契约build 写完、server 只读两边解耦任何一边单独演进都不破坏另一边。路由匹配和渲染分开先做轻量的规则匹配再委派给对应路由模块新增一种路由类型比如 API、Route Handler不用动主干管道。给每个阶段挂 trace spanNext.js 的构建代码本身就是性能剖析数据可观测性不是事后加的是写代码时的默认动作。顺着packages/next/src/server/route-modules/app-page/看一个 App Router 页面的完整渲染链路是理解整个框架最高效的下一站。【免费下载链接】next.jsThe React Framework项目地址: https://gitcode.com/GitHub_Trending/next/next.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表