模块方法
当使用 Rspack 打包应用程序时,你可以选择多种模块语法风格,包括 ES modules 和 CommonJS。
尽管 Rspack 支持多种模块语法,但我们还是建议尽量使用一致的语法,以此避免一些奇怪的行为和 bug。
事实上,当距离最近的 package.json 文件中 "type" 字段值为 "module" 或 "commonjs" 时,Rspack 会对 .mjs 文件、.cjs 文件或.js 文件进行对应的处理:
- 文件后缀为
.mjs,或者package.json中"type": "module"且后缀为.js时:- 不允许使用 CommonJS,如
require,module.exports或exports - 引入文件时需指定扩展名,例如,应使用
import './src/App.mjs',而非import './src/App'
- 不允许使用 CommonJS,如
- 文件后缀为
.cjs,或者package.json中"type": "commonjs"且后缀为.js时:- 不允许使用 ESM,如
import和export
- 不允许使用 ESM,如
ES modules (推荐)
Rspack 原生支持 ES modules 语法,可以使用静态的 import、export 和 import() 语法。
如果使用其他的 ES6+ 特性,你仍然需要引入 SWC 或 Babel 进行转换。
import
静态 import 另一个模块的 export。
你还可以 import Data URI,这允许你直接在导入语句中嵌入 Base64 编码的 JavaScript 代码:
export
将任何内容作为默认导出或具名导出。
Dynamic import()
动态加载模块,参考 Dynamic import 了解更多。
对 import() 的调用被视为分割点,这意味着请求的模块及其子模块被拆分成单独的 chunk。
此功能内部依赖于 Promise。如果你在旧版浏览器中使用 import(),请记得使用类似于 core-js, es6-promise 或 promise-polyfill 的 polyfill 来模拟 Promise。
import() 中的动态表达式
import() 无法使用完全动态的导入语句,例如 import(foo)。因为 foo 可能是系统或项目中任何文件的任何路径。
import() 必须至少包含一些关于模块所在位置的信息。可以将打包限制在特定目录或一组文件中,这样当你使用动态表达式时,在 import() 调用中可能被请求的每个模块都会被包括进来。
例如,import(./locale/${language}.json) 会将 ./locale 目录中的每个 .json 文件都被打包进新的代码块。在运行时,一旦变量 language 被计算出来,任何像 english.json 或 german.json 这样的文件都将可供使用。
import() 中的魔法注释
通过向 import 语句添加注释,可以指定 chunk 名称、加载模式等行为。
从 Rspack 2.1.0 开始,推荐使用下方的 rspack 前缀魔法注释。对应的 webpack 前缀注释仍会被兼容支持,例如 webpackIgnore 等价于 rspackIgnore。
下方示例统一使用 rspack 前缀;如需兼容 webpack,可以将其替换为对应的 webpack 前缀。
rspackIgnore
- 类型:
boolean - webpack 兼容名称:
webpackIgnore
设置为 true 时,Rspack 将跳过对该动态导入的静态分析和打包处理。具体表现为:
- 构建时不会分析该模块的依赖关系
- 该模块不会被打包为独立的 chunk 文件
- 导入操作将在运行时由浏览器原生
import()执行
这在需要从外部 CDN 动态加载 ESM 格式的第三方库时特别有用,例如:
rspackIgnore 同样适用于 new URL() 语法。默认情况下,Rspack 会解析 new URL() 中的模块标识符,并将其引用的模块打包到构建产物中。当你需要 Rspack 跳过某个 new URL() 的处理时,可以添加 rspackIgnore: true 注释:
rspackMode
- 类型:
"eager" | "lazy" | "weak" | "lazy-once" - webpack 兼容名称:
webpackMode - 默认值:
'lazy'
可以指定以不同的模式解析动态导入。支持以下选项:
'lazy'(默认值):为每个可能导入的模块生成一个可延迟加载的 chunk。'lazy-once':将动态导入上下文中的所有可能模块生成到同一个异步 chunk 中。第一次调用import()时加载该 chunk,后续调用会复用它。此模式适用于import('./locales/' + language + '.json')这类可能匹配多个模块的动态表达式。'eager':不生成额外的 chunk,而是将所有可能的模块放入当前 chunk,因此不会产生额外的网络请求。import()仍然返回 Promise,且模块要等到调用import()时才会执行。'weak':仅在模块已通过其他方式加载时才解析成功,例如模块已包含在另一个加载完成的 chunk 中。此模式不会发起网络请求;如果模块不可用,Promise 会被拒绝。它主要用于由服务端确保所需 chunk 已包含在初始响应中的 SSR 场景。
例如,使用 lazy-once 将所有可能的语言模块合并到同一个异步 chunk 中:
rspackPrefetch
- 类型:
number:预取优先级boolean:false表示不预取,true表示预取且优先级为0
- webpack 兼容名称:
webpackPrefetch
告诉浏览器将来可能需要该资源来进行某些导航跳转,详情请查看预取/预载模块。
例如,当父 chunk 加载后,浏览器会在空闲时预取编辑器 chunk:
也可以使用数字设置预取优先级:
rspackPreload
- 类型:
number:预载优先级boolean:false表示不预载,true表示预载且优先级为0
- webpack 兼容名称:
webpackPreload
告诉浏览器在当前导航期间可能需要该资源,详情请查看预取/预载模块。
例如,在加载父 chunk 的同时预载图表库:
rspackChunkName
- 类型:
string - webpack 兼容名称:
webpackChunkName
指定新 chunk 的名称。
最终文件名仍由 output.chunkFilename 决定。
rspackFetchPriority
- 类型:
"low" | "high" | "auto" - webpack 兼容名称:
webpackFetchPriority
为指定的动态导入设置 fetchPriority。也可以通过使用 module.parser.javascript.dynamicImportFetchPriority 选项为所有动态导入设置全局默认值。
例如,为首屏关键模块设置较高的获取优先级:
rspackInclude
- 类型:
RegExp - webpack 兼容名称:
webpackInclude
在导入解析时匹配的正则表达式。只有匹配的模块才会被打包。
例如,只将 ./locales 目录中的 .json 文件纳入动态导入上下文:
rspackExclude
- 类型:
RegExp - webpack 兼容名称:
webpackExclude
在导入解析时匹配的正则表达式。只有匹配的模块不会被打包。
例如,排除 ./locales 目录中的测试文件:
rspackInclude 和 rspackExclude 只会筛选静态路径前缀(例如 ./locales)下发现的候选模块,不会改变该前缀。等价的 webpackInclude 和 webpackExclude 注释也会被兼容支持。
rspackExports
- 类型:
string | string[] - webpack 兼容名称:
webpackExports
使 Rspack 在处理该动态 import() 模块时仅打包指定的导出。这样可以降低 chunk 的产物体积。
例如,当导入结果传给其他函数、Rspack 无法静态推断具体使用了哪些导出时,可以显式声明需要的导出:
如果代码直接访问导入模块的属性或对其进行解构,Rspack 通常可以自动推断使用的导出,无需添加 rspackExports。
CommonJS
Rspack 也支持 CommonJS 语法,可以使用 require 和 module.exports 语法。
require
以同步的方式引入其他模块。
require.resolve
以同步的方式获取模块的 ID。此方法会将模块打包进最终的 bundle 中,但不会执行模块代码。返回的模块 ID 主要用于与 require.cache[id] 或 Rspack 内部的 __webpack_require__(id) 一起使用,在大多数应用场景中应避免直接使用此方法。
模块 ID 的类型可以是 number 或 string,具体取决于 optimization.moduleIds 配置。
require.cache
多处引用同一模块,最终只会产生一次模块执行和一次导出。所以,会在运行时(runtime)中会保存一份缓存。删除此缓存,则会产生新的模块执行和新的导出。
require.context
require.context 允许你动态地 require 一组模块。
你可以在代码中使用 require.context,Rspack 将在构建时进行解析并引用匹配的模块。
require.context 的返回值与 import.meta.webpackContext 相同。
- 类型:
- 示例:
Rspack 在编译时,会通过静态分析来解析 require.context 的参数,因此参数必须是字面量。
例如,filter 的值不允许传入一个变量,也不允许传入 new RegExp() 生成的值,只能是一个正则表达式字面量。
require.ensure
建议使用更符合标准的 import() 来替代 require.ensure()。
将给定 dependencies 单独打包,并异步加载这些依赖。
- Type:
- 该特性内部依赖于 Promise。 如果你在旧的浏览器上使用
require.ensure, 最好加入 polyfill es6-promise 或 promise-polyfill。 - 和 webpack 一样,callback 函数也可以接收一个名为 require 的参数(且必须名为 require),该 require 参数和 cjs 的 require 全局变量一致,但我们建议直接使用全局的 require 来加载模块而不是该 require 参数,因为 loader 可能会将其重命名导致依赖分析失败。
- Example:
require.resolveWeak
与 require.resolve 类似,但是不会把 module 打包到最终的 bundle 中。是 "弱(weak)" 依赖。
示例:
Data URI 模块
Rspack 支持使用 import 和 require 语法导入 Data URI 模块。
- import
- require
除此之外,还支持了 Base64 编码:
Data URI 模块可以被用作虚拟模块(Virtual Modules)的实现方式,如:配合 loader 完成运行时动态加载自定义模块。
内置 Rules
Rspack 默认支持这些 MIME 类型 的 data URI 模块:application/json、text/javascript、application/javascript、application/node 和 application/wasm。这意味着当你使用这些 MIME 类型创建 data URI 模块时,Rspack 会自动识别他们。
Rspack 内置的 MIME rules 如下:
自定义 Rules
你可以也使用 rules[].mimetype 来扩展 Data URI 模块的匹配规则,例如为 text/javascript 添加自定义的 loaders:
本页改编自 webpack 文档,遵循 CC BY 4.0,且已作修改。

