CC 4.0 协议
本节内容派生于以下链接指向的内容 ,并遵守 CC BY 4.0 许可证的规定。
以下内容如果没有特殊声明,可以认为都是基于原内容的修改和删减后的结果。
Experiments
该选项允许用户开启和尝试一些实验性的功能。
- 类型:
object
:::tip
在 minor release 中,Rspack 可能对这些实验性特性的 public API 做一些调整,并在更新日志中对这些变动进行详细的说明。因此,如果你使用了实验性特性,请留意 minor 版本的更新日志。
:::
experiments.asyncWebAssembly
支持基于新规范的 WebAssembly,这使 WebAssembly 模块成为异步模块。
rspack.config.mjs
export default {
experiments: {
asyncWebAssembly: true,
},
};
当设置 experiments.futureDefaults 为 true
时,默认启用此功能。
experiments.outputModule
开启之后,将尽可能输出符合 ECMAScript 语法的代码。例如,使用 import()
加载 chunk,使用 ESM exports 等等。
rspack.config.mjs
export default {
experiments: {
outputModule: true,
},
};
experiments.css
启用原生 CSS 支持和 CSS 相关的 parser 和 generator options:
基本示例:
rspack.config.mjs
export default {
experiments: {
css: true,
},
};
experiments.futureDefaults
使用下一个主版本 Rspack 的默认值,并在任何有问题的地方显示警告。
rspack.config.mjs
export default {
experiments: {
futureDefaults: true,
},
};
experiments.topLevelAwait
开启打包 Top-level await 的支持,Top-level await
仅能在 ModuleType 为 javascript/esm
的模块中使用。
默认开启,可通过该配置关闭:
rspack.config.mjs
export default {
experiments: {
topLevelAwait: false,
},
};
experiments.lazyCompilation
- 类型:
boolean | LazyCompilationOptions
- 默认值:
false
type LazyCompilationOptions =
| boolean
| {
/**
* 为 entries 启用 lazy compilation
*/
entries?: boolean;
/**
* 为 dynamic imports 启用 lazy compilation
*/
imports?: boolean;
/**
* 指定哪些导入的模块应该被延迟编译
*/
test?: RegExp | ((m: Module) => boolean);
/**
* 自定义客户端脚本路径。
*/
client?: string;
/**
* 自定义服务端路径
*/
serverUrl?: string;
};
开启懒编译,这对提高多入口应用(MPA)或大型单页面应用(SPA)的 dev 启动性能会非常有帮助。例如你有二十个入口,只有访问到的入口才会进行构建,或者如果项目中存在非常多的 import()
,每一个 import()
所指向的模块都只有在被真正访问到时,才进行构建。
如果设置为 true,则默认会对入口模块以及 import()
指向的模块进行懒编译。你可以通过配置对象形式,来决定是否只对入口或只对 import()
生效。entries
决定是否对入口生效,import()
决定是否对 import()
生效。
rspack.config.mjs
const isDev = process.env.NODE_ENV === 'development';
export default {
experiments: {
// 仅在 dev 模式下开启
lazyCompilation: isDev,
},
};
除此以外你还可以配置 test
来更细粒度控制对哪些模块进行懒编译。test
可以是一个正则表达式,只对该正则匹配到的模块进行懒编译,test
也可以是一个函数,函数的输入是 Module
类型,返回 boolean
类型,表示是否命中懒编译逻辑。
NOTE
当前 lazy compilation 仍处于实验性阶段。在部分场景下,lazy compilation 可能无法按照预期工作,或是性能提升不明显。
lazyCompilation.client
用于覆盖默认 lazy compilation 的客户端运行时,如果你想要自定义客户端运行时的逻辑,可以通过该配置项来指定。
你可以参考默认实现:
rspack.config.mjs
import path from 'path';
export default {
experiments: {
lazyCompilation: {
client: path.resolve('custom-client.js'),
},
},
};
lazyCompilation.serverUrl
告诉客户端需要请求的服务端路径,默认为空,在浏览器环境会找到页面所在的服务端路径,但在 Node 环境下需要显式指定具体的路径。
rspack.config.mjs
export default {
experiments: {
lazyCompilation: {
serverUrl: 'http://localhost:3000',
},
},
};
排除 HMR client
如果你未使用 Rspack 的 dev server,而是使用自己的 server 作为开发服务器,一般会在 entry 配置中加入另外的 client 代码来开启 HMR 等能力,那么最好通过配置 test 来将该 client 模块从懒编译模块中排除出去。
如果不排除掉,并且开启 entry 的懒编译,该 client 在第一次访问页面时不会被编译,因此需要一次额外的刷新才能让其真正生效。
rspack.config.mjs
import { rspack } from '@rspack/core';
const options = {
experiments: {
lazyCompilation: {
test(module) {
const isMyClient = module.nameForCondition().endsWith('dev-client.js');
// 让 dev-client.js 不被懒编译
return !isMyClient;
},
},
},
};
const compiler = rspack(options);
new compiler.webpack.EntryPlugin(compiler.context, 'dev-client.js', {
// name: undefined 代表这是全局 entry,会插入到每一个 entry 前
name: undefined,
}).apply(compiler);
experiments.layers
控制是否启用 layer 功能,layer 可以为模块图中以一个模块作为起点的子图中的所有模块添加标识符前缀,用来与其他不同 layer 的模块进行区分,比如:
index.js
模块的 layer 为默认的 null
,其 identifier
为 ./index.js
,我们为其添加 layer = 'client'
,其 identifier
会变成 (client)/./index.js
,这时这两个不同 layer 的 index.js
会被区分为不同的模块,因为其唯一标识 identifier
不一样,最终产物中也会存在这两个模块的产物。
模块默认的 layer 为 null
,模块默认会继承其父模块的 layer,你可以通过 entryOptions.layer
为一个入口模块添加 layer,也可以通过 module.rule[].layer
为匹配到的模块添加 layer,同时可以通过 module.rule[].issuerLayer
根据父模块的 layer 进行匹配。
rspack.config.mjs
export default {
experiments: {
layers: true,
},
};
experiments.incremental
type Incremental = {
make?: boolean;
inferAsyncModules?: boolean;
providedExports?: boolean;
dependenciesDiagnostics?: boolean;
sideEffects?: boolean;
buildChunkGraph?: boolean;
moduleIds?: boolean;
chunkIds?: boolean;
modulesHashes?: boolean;
modulesCodegen?: boolean;
modulesRuntimeRequirements?: boolean;
chunksRuntimeRequirements?: boolean;
chunksHashes?: boolean;
chunksRender?: boolean;
emitAssets?: boolean;
};
是否增量地进行重构建,加快重构建或 HMR 的速度,建议仅在开发时启用:
rspack.config.mjs
const isDev = process.env.NODE_ENV === 'development';
export default {
mode: isDev ? 'development' : 'production',
experiments: {
incremental: isDev,
},
};
true
表示对全部阶段启用增量,false
表示对全部阶段关闭增量,也可以仅对指定的部分阶段开启增量:
rspack.config.mjs
export default {
experiments: {
// 对全部阶段启用增量
incremental: true,
// 对全部阶段关闭增量
incremental: false,
// 仅对指定的部分阶段开启增量
incremental: {
make: true,
emitAssets: true,
},
},
};
目前 Rspack 默认开启 make
和 emitAssets
阶段的增量,这也是之前 Rspack v1.0 的默认行为。随着该特性的进一步稳定,我们会默认开启更多阶段的增量,直到完全启用。
TIP
该特性属于实验性特性,可前往 rspack#8106 查看其相关进度,也可在此 issue 中反馈 bugs 以及任何与之相关的反馈信息。
experiments.parallelCodeSplitting
开启后会启用新的多线程 code splitting 算法,如果你的项目中包含较多的动态引用,开启后可以显著降低 code splitting 阶段耗时,1.3.0 版本默认开启。
rspack.config.mjs
export default {
experiments: {
parallelCodeSplitting: true,
},
};
experiments.parallelLoader
开启并行 loader,你需要使用 Rule.use.parallel
手动为各个 loader 分别开启并行模式。开启后,对应的 loader 会被发送到 worker threads 执行。
rspack.config.mjs
export default {
module: {
rules: [
{
test: /\.less$/,
use: [
{
loader: 'less-loader',
parallel: true,
options: {
// loader options
},
},
],
},
],
},
experiments: {
parallelLoader: true,
},
};
experiments.rspackFuture
用于控制是否开启 Rspack 未来的默认行为,详情请参考这里。
rspackFuture.bundlerInfo
-
类型:
type BundlerInfo = {
version?: string,
bundler?: string,
force?: ('version' | 'uniqueId')[] | boolean;
};
用于在生成产物中注入当前使用的 Rspack 信息。其中:
version
:用于指定 Rspack 版本,默认读取 @rspack/core/package.json
中的 version
字段。
bundler
:用于指定打包工具名称,默认为 rspack
force
:是否强制注入 Rspack 信息,会以运行时模块的形式加入到产物中,默认为 true
即强制注入,可通过数组选择强制注入的项目。
关闭默认注入
可通过将 force
设定为 false
来关闭默认注入,此时仅在检测到代码中使用了 __rspack_version__
和 __rspack_unique_id__
时才会注入:
rspack.config.mjs
export default {
experiments: {
rspackFuture: {
bundlerInfo: { force: false },
},
},
};
experiments.cache
type ExperimentCacheOptions =
| boolean
| {
type: 'memory';
}
| {
type: 'persistent';
buildDependencies?: string[];
version?: string;
snapshot?: {
immutablePaths?: Array<string | RegExp>;
unmanagedPaths?: Array<string | RegExp>;
managedPaths?: Array<string | RegExp>;
};
storage?: {
type: 'filesystem';
directory?: string;
};
};
控制实验性的缓存行为,此配置依赖全局开启缓存,需配置 config.cache 为 true
才有效。
Note
production 模式下 config.cache
默认值为 false
,这会导致此配置项失效,建议直接配置 config.cache
为 true
。
禁用缓存
可以配置 experiment.cache
为 false
来禁用缓存,这与配置 config.cache 为 false
没有差别。
rspack.config.mjs
export default {
cache: true,
experiments: {
cache: false,
},
};
内存缓存
可以配置 experiment.cache
为 true
或者 { "type": "memory" }
来启动内存缓存。
rspack.config.mjs
export default {
cache: true,
experiments: {
cache: true,
},
};
持久化缓存
可以配置 experiment.cache
为 { "type": "persistent" }
来启用持久化缓存。
rspack.config.mjs
export default {
cache: true,
experiments: {
cache: {
type: 'persistent',
},
},
};
cache.buildDependencies
cache.buildDependencies
是一个包含构建依赖的文件数组,Rspack 将使用其中每个文件的哈希值来使持久化缓存无效。
TIP
推荐添加 __filename 到 buildDependencies 中
rspack.config.mjs
export default {
cache: true,
experiments: {
cache: {
type: 'persistent',
buildDependencies: [__filename, path.join(__dirname, './tsconfig.json')],
},
},
};
cache.version
缓存数据的版本,不同版本缓存相互隔离。
cache.snapshot
配置快照策略,Snapshot 用于在热启动时判断哪些文件在停机时被修改。支持以下配置:
snapshot.immutablePaths
-
类型: (RegExp | string)[]
-
默认值: []
不可变文件的路径数组,这些文件的变动在热启动时会被忽略。
snapshot.managedPaths
由包管理器管理的路径数组,热启动时会通过 package.json 中的版本来判断是否修改。
snapshot.unmanagedPaths
-
类型: (RegExp | string)[]
-
默认值: []
指定 snapshot.managedPaths
中不受包管理器管理的路径数组。
cache.storage
-
类型: { type: 'filesystem', directory: string }
-
默认值: { type: 'filesystem', directory: 'node_modules/.cache/rspack' }
配置缓存存储,目前仅支持文件系统存储,可以通过 directory
设置缓存路径,默认为 node_modules/.cache/rspack
。
rspack.config.mjs
export default {
cache: true,
experiments: {
cache: {
type: 'persistent',
storage: {
type: 'filesystem',
directory: 'node_modules/.cache/rspack',
},
},
},
};
从 webpack config 迁移
Rspack cache 配置与 webpack cache 配置的用法存在差异, 你可以参考以下步骤对 webpack cache 配置进行迁移。
- 根据 webpack 缓存类型,设置 Rspack 缓存类型,持久化缓存继续后续步骤,其他类型缓存到这一步即可。
rspack.config.mjs
export default {
- cache: {
- type: 'filesystem',
- },
+ cache: true,
+ experiments: {
+ cache: {
+ type: 'persistent',
+ },
+ },
};
- 迁移
cache.buildDependencies
rspack.config.mjs
export default {
- cache: {
- buildDependencies: {
- config: [__filename, path.join(__dirname, "package.json")],
- ts: [path.join(__dirname, "tsconfig.json")]
- }
- },
experiments: {
cache: {
type: "persistent",
+ buildDependencies: [
+ __filename,
+ path.join(__dirname, "package.json"),
+ path.join(__dirname, "tsconfig.json")
+ ]
},
},
};
- 迁移
cache.version
& cache.name
rspack.config.mjs
export default {
- cache: {
- name: `${config.name}-${config.mode}-${otherFlags}`,
- version: appVersion
- },
experiments: {
cache: {
type: "persistent",
+ version: `${config.name}-${config.mode}-${otherFlags}-${appVersion}`
},
},
};
- 迁移
snapshot
rspack.config.mjs
export default {
- snapshot: {
- immutablePaths: [path.join(__dirname, "constant")],
- managedPaths: [path.join(__dirname, "node_modules")],
- unmanagedPaths: []
- },
experiments: {
cache: {
type: "persistent",
+ snapshot: {
+ immutablePaths: [path.join(__dirname, "constant")],
+ managedPaths: [path.join(__dirname, "node_modules")],
+ unmanagedPaths: []
+ }
},
},
};
- 迁移
cache.cacheDirectory
rspack.config.mjs
export default {
- cache: {
- cacheDirectory: path.join(__dirname, "node_modules/.cache/test")
- },
experiments: {
cache: {
type: "persistent",
+ storage: {
+ type: "filesystem",
+ directory: path.join(__dirname, "node_modules/.cache/test")
+ }
},
},
};
示例代码:
function transform(webpackConfig, rspackConfig) {
rspackConfig.experiments = rspackConfig.experiments || {};
if (webpackConfig.cache === undefined) {
webpackConfig.cache = webpackConfig.mode === 'development';
}
// 1. 如果使用禁用缓存,则直接配置 `experiments.cache` 为 `false`
if (webpackConfig.cache === false) {
rspackConfig.experiments.cache = false;
return;
}
// 2. 如果使用内存缓存,则直接配置 `experiments.cache` 为 `true`
if (webpackConfig.cache === true || webpackConfig.cache.type === 'memory') {
rspackConfig.experiments.cache = true;
return;
}
// 3. 持久化缓存 配置 `experiments.cache` 为 `{ type: "persistent" }`
rspackConfig.experiments.cache = { type: 'persistent' };
// 4. 从 webpack 配置中构建 `experiments.cache` 其他配置
rspackConfig.experiments.cache.buildDependencies = Object.values(
webpackConfig.cache.buildDependencies || {},
).flat();
rspackConfig.experiments.cache.version = [
webpackConfig.cache.name,
webpackConfig.cache.version,
].join();
rspackConfig.experiments.cache.snapshot = {
immutablePaths: webpackConfig.snapshot?.immutablePaths,
managedPaths: webpackConfig.snapshot?.managedPaths,
unmanagedPaths: webpackConfig.snapshot?.unmanagedPaths,
};
rspackConfig.experiments.cache.storage = {
type: 'filesystem',
directory: webpackConfig.cache?.cacheDirectory,
};
}
experiments.buildHttp
- 类型:
HttpUriOptions
- 默认值:
undefined
type HttpUriOptions = {
/**
* A list of allowed URIs
*/
allowedUris: (string | RegExp)[];
/**
* Define the location to store the lockfile
*/
lockfileLocation?: string;
/**
* Define the location for caching remote resources
*/
cacheLocation?: string | false;
/**
* Detect changes to remote resources and upgrade them automatically
* @default false
*/
upgrade?: boolean;
/**
* Custom http client
*/
httpClient?: (
url: string,
headers: Record<string, string>,
) => Promise<{
status: number;
headers: Record<string, string>;
body: Buffer;
}>;
};
启用此功能后,Rspack 可以构建以 http(s):
协议开头的远程资源。Rspack 会将资源下载到本地,然后再进行打包。
默认情况下,Rspack 会在 context 文件夹下生成 rspack.lock
和 rspack.lock.data
分别作为 Lockfile 和缓存的位置,你也可以通过 lockfileLocation
和 cacheLocation
进行配置。
NOTE
你应该将 lockfileLocation
和 cacheLocation
的文件提交到版本控制系统中,这样在生产构建期间不会发出网络请求。
示例:
rspack.config.mjs
export default {
experiments: {
buildHttp: {
allowedUris: ['https://'],
lockfileLocation: path.join(__dirname, 'my_project.lock'),
cacheLocation: path.join(__dirname, 'my_project.lock.data'),
},
},
};
启用此功能后,你可以直接从网址导入模块:
// Import from a remote URL
import { something } from 'https://example.com/module.js';
// Or import assets
import imageUrl from 'https://example.com/image.png';