dev.lazyCompilation
- 类型:
- 默认值:
用于开启 lazy compilation(即按需编译),基于 Rspack 的 lazy compilation 特性实现。
介绍
尽管 Rspack 本身具备良好的性能,但是面对具有大量模块的应用,其整体构建时间仍然可能不够理想。这是因为应用中的模块需要经过不同 loader 的编译,包括 postcss-loader、sass-loader、vue-loader 等,它们都会产生额外的编译开销。
Lazy compilation 是一个提升开发阶段启动性能的有效手段,它采用按需编译模块的方式,而非在启动时编译全部模块。这意味着开发者在启动 dev server 时,可以很快看到应用运行,并分次构建所需的模块。通过这种按需编译的机制,可以减少不必要的编译时间,且随着项目规模的扩大,编译时间不会显著增长,从而大幅提升开发体验。
Lazy compilation 仅在开发阶段有效,对于生产构建不会产生影响。
示例
启用 Lazy compilation
对于 web 目标,Rsbuild 默认开启 imports 选项,即 lazy 编译动态引入的模块。
将 lazyCompilation 设置为 true 即可开启完整的 lazy compilation 功能:
这等价于以下配置:
禁用 Lazy compilation
将 lazyCompilation 设置为 false 来禁用 lazy compilation:
入口模块
通过 lazyCompilation.entries 来控制是否延迟编译入口模块:
在启用 entries 选项后,当你启动 dev server 时,Rsbuild 不会编译所有的页面,而是仅在访问特定的页面时,才对该页面进行编译。
延迟编译入口模块时,有以下注意事项:
- 只适用于多页应用(MPA),对单页应用(SPA)没有优化效果。
- 当你访问一个页面时,你需要等待页面编译完成才能看到页面的内容。
异步模块
通过 lazyCompilation.imports 来控制是否延迟编译 dynamic import 引入的异步模块:
开启 imports 选项后,所有的异步模块只有在被请求时才触发编译。如果你的项目是一个单页应用(SPA),并通过 dynamic import 进行了路由拆分,那么 dev 启动时间会有明显提升。
Server URL
通过 lazyCompilation.serverUrl 可以指定 client 需要请求的 server URL。
对于 web 目标,如果未显式配置 lazyCompilation.serverUrl,Rsbuild 会在同时满足以下条件时,根据 dev.client 推导默认的 serverUrl:
- dev.assetPrefix 为
true或绝对 URL。 - 配置了 dev.client.host 或 dev.client.port。
当 dev.assetPrefix 为相对 URL 时,Rsbuild 不会根据 dev.client 推导 serverUrl。懒编译请求会发送到当前页面所在的源(origin)。
如果显式配置了 lazyCompilation.serverUrl,该配置始终优先于从 dev.client 推导出的默认值。
示例如下:
Rsbuild 会自动将 <port> 占位符替换为 server 实际监听的端口号。
Node 目标
Node 目标默认立即编译。设置 dev.lazyCompilation.node: true 可延迟编译动态导入的模块。布尔值 true 和未设置 node: true 的配置仍仅作用于浏览器目标。Node 入口始终立即编译,设置 entries: true 会报错。Node lazy compilation 要求 mode: 'development' 和 dev.hmr: true。其他模式会报错,因为热更新必须保留运行时实例。
例如,为应用自行管理的原生 runtime 配置 ES module bundle:
应用或框架负责 runtime 的生命周期:
- 使用原生
import()或require()加载一次输出的入口,并在 lazy import 等待期间保留该 runtime。 - 从入口暴露调用
import.meta.webpackHot.check(true)或module.hot.check(true)的接口。在编译成功、更新文件可用后调用该接口。按顺序应用待处理的更新,直到运行时的__webpack_hash__与成功编译的 hash 一致。Rsbuild 会安装 HMR 插件,但不会主动执行 hot check。 - 处理更新失败,并在关闭时释放 runtime、请求和 server。应用需要自行恢复 runtime 无法接受的更新。
原生 runtime 需要访问输出的 chunk 和 hot-update 文件。示例将这些文件写入磁盘,并通过 publicPath: 'auto' 让 ESM hot update 相对于输出目录解析。在 "type": "module" 的 package 中使用 CommonJS 输出时,应为 bundle 和异步 chunk 设置 .cjs 文件名,并将 tools.rspack.output.hotUpdateChunkFilename 设置为 '[id].[fullhash].hot-update.cjs'。
Node 激活端点默认使用 dev server 的协议、主机和实际端口生成绝对 HTTP(S) URL,不受 dev.client 配置影响。显式设置的 HTTP(S) serverUrl 优先,并支持 <port>。使用外部托管的 dev middleware 时,应将 serverUrl 设置为可访问的宿主端点。
Runtime 的管理方还需要定义由哪个模块接受更新。模块接受自身更新时不会通知父模块,因此先前返回的模块引用可能保持不变。Lazy boundary 可以接受静态依赖的更新,并通过 getter 读取更新后的 binding:
入口可以只 lazy 导入一次该 boundary,并在更新后调用 getValue()。发生变化的 value.js 模块需要将更新传播到 boundary,而不是接受自身更新。
Rsbuild 不会保留或热更新 environment.loadBundle 创建的 runtime。Node 输出仍不通过 HTTP 提供为静态资源。框架需要协调接受更新的模块边界、路由 manifest、loader 更新与保留的 runtime。

