NextJS如何检测获取新页面?Webpack按需Chunk加载配置原理
场景复现
在全新 Next.js 项目中执行 yarn dev 启动开发服务器,在 pages/index.jsx 中添加如下代码:
export default function Home(){ return <Link href="/abc">Go to abc</Link> }
接着在 pages 目录创建 abc.js 页面文件,代码如下:
export default function AbcPage(){ return <div>Welcome to ABC page.</div> }
此时观察终端输出会发现,新创建的 abc.js 页面并未被编译;只有当点击首页的「Go to abc」链接时,才会触发该页面的编译流程,对应的 abc.js chunk 文件随后在浏览器中完成下载。
核心问题
Next.js 是如何配置 Webpack 实现页面 chunk 按需加载的?
注:已查看以下相关源码文件,其中 flight-client-entry-plugin.ts 被判断为核心文件:
packages/next/build/webpack/loaders/next-client-pages-loader.tspackages/next/client/index.tsxpackages/next/client/page-loader.tspackages/next/build/webpack/plugins/flight-client-entry-plugin.ts
实现机制解析
Next.js 针对页面的按需加载,是通过定制 Webpack 配置+自研 loader/plugin+运行时逻辑的组合方案实现的,核心围绕「延迟编译+动态加载」展开:
1. 动态入口生成(flight-client-entry-plugin.ts 作用)
这个插件不会把 pages/ 下的所有文件直接作为 Webpack 入口,而是生成一个动态入口文件。该入口仅维护页面路径与加载函数的映射,不会直接引入任何页面组件代码,确保初始构建时不会打包所有页面。
2. 页面引用的动态转换(next-client-pages-loader.ts 作用)
当代码中出现 <Link href="/abc"> 这类页面跳转时,这个自定义 Loader 会将静态的页面引用转换为动态 import 语法,转换后的逻辑类似:
const loadAbcPage = () => import('../pages/abc.js')
Webpack 识别到 import() 后,会自动将该页面打包为独立 chunk,且不会在初始构建阶段编译这个 chunk。
3. 运行时的按需触发逻辑
开发环境下,page-loader.ts 和 client/index.tsx 中的运行时代码会处理页面跳转的完整流程:
- 用户点击
<Link>时,客户端先检查目标页面的 chunk 是否已存在; - 若未编译,会向开发服务器发起编译请求,服务器触发对应页面的 Webpack 编译;
- 编译完成后,客户端通过动态 import 加载对应的 chunk,最终完成页面渲染。
4. Webpack 底层配置支撑
Next.js 会给 Webpack 配置针对性的 splitChunks 规则,保证每个页面都被打包为独立的 chunk;同时启用 output.asyncChunks 选项,允许 Webpack 生成支持异步加载的 chunk 文件。开发环境下还会配置热更新相关参数,确保按需编译后的 chunk 能实时被客户端获取并更新。
内容的提问来源于Stack Exchange,提问作者Shyam Swaroop

