实验特性配置
title: 实验特性配置
sort: 19
contributors:
- EugeneHlushko
- wizardofhogwarts
- chenxsan
- anshumanv
- snitin315
- burhanuday
experiments
boolean: false
experiments 选项在 webpack 5 中引入,用于让用户能够启用和尝试实验性功能。
W> 由于实验性功能具有宽松的语义化版本控制,并且可能包含破坏性变更,请确保将 webpack 版本固定到 minor 版本,例如 webpack: ~5.4.3 而不是 webpack: ^5.4.3,或者在使用 experiments 时使用 lockfile。
可用选项:
asyncWebAssembly:根据更新后的规范支持新的 WebAssembly,它将 WebAssembly 模块变为异步模块。自 webpack 5.109.0 起默认为'auto',即除非为 WebAssembly 文件注册了 loader,否则启用内置支持。backCompatbuildHttpcacheUnaffectedcssdeferImportfutureDefaultshtmllazyCompilationoutputModuletypescriptsourceImportsyncWebAssembly:像 webpack 4 那样支持旧的 WebAssembly。layers:启用模块和 chunk 层级,自5.102.0起已移除并且无需额外选项即可工作。topLevelAwait:当在顶层使用await时,将模块转换为async模块。从 webpack 版本5.83.0开始(但在之前的版本中,可以通过将experiments.topLevelAwait设置为true来启用),此功能默认启用,自5.102.0起已移除并且无需额外选项即可工作。
webpack.config.js
js
export default {
// ...
experiments: {
asyncWebAssembly: true,
buildHttp: true,
lazyCompilation: true,
outputModule: true,
sourceImport: true,
syncWebAssembly: true,
topLevelAwait: true,
},
};
experiments.backCompat
启用向后兼容层,并对许多 webpack 4 API 发出弃用警告。
- 类型:
boolean
js
export default {
// ...
experiments: {
backCompat: true,
},
};
experiments.buildHttp
启用后,webpack 可以构建以 http(s): 协议开头的远程资源。
-
类型:
-
(string | RegExp | ((uri: string) => boolean))[] -
HttpUriOptionsts{ allowedUris: (string|RegExp|(uri: string) => boolean)[], cacheLocation?: false | string, frozen?: boolean, lockfileLocation?: string, upgrade?: boolean }
-
-
可用版本:5.49.0+
-
示例
webpack.config.js
jsexport default { // ... experiments: { buildHttp: true, }, };js// src/index.js import pMap1 from "https://cdn.skypack.dev/p-map"; // 启用 `buildHttp` 后,webpack 会像处理普通本地模块一样构建 pMap1 console.log(pMap1);
experiments.buildHttp.allowedUris
允许的 URI 列表。
-
类型:
(string|RegExp|(uri: string) => boolean)[] -
示例
webpack.config.js
jsexport default { // ... experiments: { buildHttp: { allowedUris: [ "http://localhost:9990/", "https://raw.githubusercontent.com/", ], }, }, };
experiments.buildHttp.cacheLocation
定义缓存远程资源的位置。
-
类型
stringfalse
-
示例
webpack.config.js
jsexport default { // ... experiments: { buildHttp: { cacheLocation: false, }, }, };
默认情况下,webpack 会使用 <compiler-name.>webpack.lock.data/ 进行缓存,但你可以通过将其值设置为 false 来禁用缓存。
请注意,你应该将 experiments.buildHttp.cacheLocation 下的文件提交到版本控制系统中,因为在 production 构建期间不会发起任何网络请求。
experiments.buildHttp.frozen
冻结远程资源和 lockfile。对 lockfile 或资源内容的任何修改都将导致错误。
- 类型:
boolean
experiments.buildHttp.lockfileLocation
定义存储 lockfile 的位置。
- 类型:
string
默认情况下,webpack 会生成一个 <compiler-name.>webpack.lock 文件。请确保将其提交到版本控制系统中。在 production 构建期间,webpack 将根据 lockfile 和 experiments.buildHttp.cacheLocation 下的缓存来构建以 http(s): 协议开头的模块。
experiments.buildHttp.proxy
指定用于获取远程资源的代理服务器。
- 类型:
string
默认情况下,webpack 会从 http_proxy(不区分大小写)环境变量中推断用于获取远程资源的代理服务器。不过,你也可以通过 proxy 选项指定代理。
experiments.buildHttp.upgrade
检测远程资源的变化并自动升级它们。
- 类型:
boolean
experiments.css
启用原生 CSS 支持。请注意,这仍然是一个正在开发中的实验性功能,将在 webpack v6 中默认启用,但你可以在 GitHub 上跟踪进展。
- 类型:
boolean | 'auto' - 默认值:
'auto'
自 webpack 5.109.0 起,该选项默认为 'auto':除非 module.rules 中已有带 loader(或显式模块类型)的规则匹配 .css 或 .module.css 文件,否则启用内置 CSS 支持,因此现有的 css-loader/mini-css-extract-plugin 配置可以保持不变。将其设置为 true 以强制使用原生支持,或设置为 false 以完全禁用。experiments.futureDefaults 会将其解析为 true。
实验性功能:
-
CSS Modules 支持:webpack 会为每个 CSS 类生成唯一的名称。使用
.module.css扩展名来启用 CSS Modules。webpack 原生支持 CSS Modules 的
composes属性,允许你从同一文件、其他 CSS 模块或全局类中组合类:css/* styles.module.css */ .base { color: blue; } .button { composes: base; padding: 10px; } .primary { composes: button; background: blue; } /* 从另一个 CSS 模块中组合 */ .composed { composes: className from "./other.module.css"; } /* 从全局类中组合 */ .globalComposed { composes: global-class from global; } -
解析 package.json文件中的样式特定字段:webpack 会查找package.json文件中的style字段,如果在 CSS 文件内部有导入,则使用该字段。例如,如果你在 CSS 文件中添加
@import 'bootstrap';,webpack 会在node_modules中查找bootstrap,并使用其package.json中的style字段。如果找不到style字段,webpack 将使用main字段以保持向后兼容。 -
CSS 文件的内容哈希:webpack 会为 CSS 文件生成内容哈希,并将其用于文件名中。这对于长期缓存非常有用。
-
CSS 提取:webpack 会将 CSS 提取到单独的文件中。此功能替代了
mini-css-extract-plugin和css-loader的需求,因为它提供了原生支持。 -
CSS 导入:webpack 会将 CSS 导入内联到生成的 CSS 文件中。
-
热模块替换(HMR):webpack 支持 CSS 文件的 HMR。这意味着对 CSS 文件所做的更改将无需完全重新加载页面即可反映在浏览器中。
-
CSS Modules 的作用域提升(模块拼接)。当
optimization.concatenateModules
启用时,exportType为text、css-style-sheet、
style或link的 CSS Modules 会被拼接为单个模块实例,而不是作为独立的运行时实例存在。这减少了开销,并为 CSS 密集型打包产物生成更小的输出。 -
@value标识符可以用作@import的路径参数以及url()引用中,因此共享路径和资源可以定义一次并在多个样式表中复用。带引号("./x"、'./x')和不带引号(./x)的形式都被接受,并会通过 webpack 常规的资源管线进行解析。css@value path: "./other.module.css"; @import path; @value bg: "./image.png"; .a { background: url(bg); }
experiments.cacheUnaffected
启用对未更改且仅引用未更改模块的模块进行额外的内存缓存。
- 类型:
boolean
默认值为 futureDefaults 的值。
experiments.deferImport
启用 tc39 提案 the import defer proposal 的支持。这允许将模块的求值延迟到首次使用时。这对于在由于 import() 的异步特性而无法使用时,需要同步延迟代码执行的情况非常有用。
- 类型:
boolean
此功能要求运行时环境支持 Proxy(ES6)。
启用以下语法:
{/* eslint-skip */}
js
import defer * as module from "module-name";
import * as module2 from /* webpackDefer: true */ "module-name2";
// 或者使用动态导入
import.defer("module-name3");
import(/* webpackDefer: true */ "module-name4");
export function f() {
// module-name 被同步求值,然后对其调用 doSomething()。
module.doSomething();
}
魔术注释(/* webpackDefer: true */)的限制
建议将魔术注释放在 from 关键字之后。其他位置可能有效,但尚未经过测试。
将魔术注释放在 import 关键字之后与文件系统缓存不兼容。
{/* eslint-skip */}
js
import /* webpackDefer: true */ * as ns from "..."; // 已知不可用
import * as ns from /* webpackDefer: true */ "..."; // 推荐写法
你应该确保你的 loader 不会移除魔术注释。
TypeScript、Babel、SWC 和 Flow.js 可以配置为保留魔术注释。
Esbuild 不兼容此功能(参见 evanw/esbuild#1439 和 evanw/esbuild#309),但它可能会在将来支持此功能。
import.defer() 现在支持 ContextModule(导入路径是动态表达式)。参见懒加载指南中的示例。
experiments.sourceImport
启用 tc39 提案 Source Phase Imports 的支持。
该提案引入了一种在_源阶段_导入模块而不是立即对其求值的方式。在 webpack 中,此实验性支持目前针对 WebAssembly 模块实现:你首先获得一个已编译的 WebAssembly.Module,然后使用你自己的导入稍后对其进行实例化。对 JavaScript 源导入的支持计划在将来的版本中提供。
- 类型:
boolean
与 asyncWebAssembly 一起启用:
js
// webpack.config.js
export default {
// ...
experiments: {
asyncWebAssembly: true,
sourceImport: true,
},
};
然后使用静态或动态源阶段语法导入 .wasm:
text
// 静态形式
import source wasmModule from "./module.wasm";
// 动态形式
const wasmModule2 = await import.source("./module.wasm");
const instance = await WebAssembly.instantiate(wasmModule);
webpack 仓库中提供了完整示例:examples/wasm-simple-source-phase。
experiments.futureDefaults
使用下一个主要版本的 webpack 默认值,并在有问题的位置显示警告。
webpack.config.js
js
export default {
// ...
experiments: {
futureDefaults: true,
},
};
experiments.html
启用原生 HTML 模块支持。从 JavaScript 导入 .html 文件会将其标签引用经过常规的 webpack 管线处理,取代了 html-loader 多年来的角色。该标志在 NormalModuleFactory 上注册了 html 模块类型,并解锁了下面描述的 HTML 行为。
- 类型:
boolean | 'auto' - 默认值:
false,自 webpack 5.109.0 起为'auto'
自 webpack 5.109.0 起,该选项默认为 'auto':除非 module.rules 中已有带 loader(或显式模块类型)的规则匹配 .html 文件,否则启用内置 HTML 支持,因此现有的 html-loader 配置可以保持不变。experiments.futureDefaults 会将其解析为 true。
webpack.config.js
js
export default {
// ...
experiments: {
html: true,
},
};
然后从 JavaScript 导入 HTML 文件。默认导出是处理后的 HTML 字符串,所有资源引用都通过 webpack 解析:
js
// src/index.js
import page from "./page.html";
document.documentElement.innerHTML = page;
W> 此功能是实验性的且不完整。 Webpack 5.107 实现了 html-loader 的角色:从 JS 导入 HTML 文件会将其标签引用经过 webpack 管线处理。自 5.108 起,.html 文件也可以用作入口,当启用此实验特性时,默认的 ./src 入口会解析到 index.html(参见下面的 HTML 作为默认入口)。与 html-webpack-plugin 的完全对等仍在进行中;整体工作跟踪在 issue #536 中。
T> HTML 解析器可以通过 module.parser.html 进行调优:使用 sources 禁用或自定义 URL 属性提取,使用 template 在解析之前转换 HTML 源。
内联 <style> 标签
HTML 模块中的内联 <style> 块会作为虚拟 CSS 模块(exportType: "text")经过 webpack 的 CSS 管线处理。url() 和 @import 引用相对于 HTML 文件进行解析,处理后的 CSS 文本会写回生成的 HTML 字符串中原始的 <style> 标签内。
html
<!-- src/page.html -->
<!doctype html>
<html>
<head>
<style>
@import "./reset.css";
body {
background: url("./bg.png");
}
</style>
</head>
<body>
...
</body>
</html>
<style type="text/css"> 和没有 type 属性的 <style> 会被处理。任何非 CSS 的 type 都会原样传递。
内联 <script> 标签
内联 <script> 主体会经过与 <script src> 相同的入口管线处理。每个 <script> 主体都会成为自己的 webpack 入口:经典的内部脚本以 CommonJS 形式打包,而 <script type="module"> 主体以 ESM 形式打包。生成的 HTML 中的标签会被重写为指向生成 chunk 的 <script src="…">,主体被清空。
html
<!-- src/page.html -->
<!doctype html>
<html>
<body>
<script type="module">
import { greet } from "./lib.js";
greet("world");
</script>
<script>
console.log("classic inline script");
</script>
</body>
</html>
适用于外部 <script src> 的相同行为在这里同样适用:
- 当
output.module启用时,经典的内联<script>标签会自动升级为type="module",与<script src>的自动升级行为一致。 webpackIgnore也适用于内联<script>标签,会保留原始主体不变。- 非 JS 的
type值(如application/ld+json和importmap)会原样传递。
<script src> 和 <link rel="modulepreload">
HTML 模块中的 <script src> 和 <link rel="modulepreload"> 引用会成为真正的 webpack 入口。生成的 chunk URL 会被重写回 HTML 字符串中,因此带哈希的文件名的工作方式与 JavaScript 导入相同。
html
<!-- src/page.html -->
<!doctype html>
<html>
<head>
<link rel="modulepreload" href="./preloaded.js" />
</head>
<body>
<script src="./entry.js"></script>
<script src="./second.js"></script>
</body>
</html>
需要注意的一些行为:
- 同一页面上的多个
<script src>标签共享同一个 runtime。在每个组(经典或type="module")内,领头者持有 runtime,其余的声明在其上dependOn。 <link rel="modulepreload">入口保持独立,永远不会被兄弟脚本导入,从而保留"预加载但不执行"的语义。- 当
output.module启用时,经典的<script src>标签会自动升级为<script type="module" src>,以便生成的 ES-module chunk 以正确的模式加载。 - 非 JS 的脚本类型(
application/ld+json、importmap等)和数据 URI 会原样传递,不会作为 JS 打包。
webpackIgnore 魔术注释
在标签之前放置 HTML <!-- webpackIgnore: true --> 注释,会告诉 webpack 跳过对该标签的 src、href、srcset 及类似属性的 URL 解析。完整的描述参见魔术注释。
HTML 作为默认入口
当启用 experiments.html 时,.html 会被添加到默认的 resolve.extensions 中,排在 JavaScript 扩展名之前,因此像 entry: "./src" 这样的目录入口会解析到 ./src/index.html,即使 ./src/index.js 也存在。这使构建以 HTML 为先,类似于 Vite 或 Parcel。
js
export default {
experiments: { html: true },
entry: "./src", // 解析到 ./src/index.html
};
当 experiments.css 启用时,.css 也会被追加到默认扩展名中,因此当没有匹配的 HTML 或 JS 时,默认入口可以回退到 ./src/index.css。只有在相应的实验特性开启时才会添加这些扩展名,因此默认构建保持不变。
热模块替换
HTML 模块支持热模块替换。无需额外配置。当 HMR 启用时(例如通过 devServer.hot),它会自动激活。
对于提取为真实 .html 文件的页面,每次热更新会在原地修补 document.body.innerHTML 和 document.title,而不是触发完全重新加载。对 <head> 中除 <title> 之外的更改(新的 <meta>、替换的 <link rel="icon"> 等)无法安全地进行 DOM 修补,因此 shim 会回退到完全重新加载页面。
T> 当 HMR 激活时,HTML 模块会禁用模块拼接,因为每个模块都需要自己的 module.hot 作用域来接受更新。
HtmlModulesPlugin 钩子
插件可以通过 webpack.html.HtmlModulesPlugin 注入和转换生成的 HTML,该插件暴露了 injectTags、transformTags、transformHtml 和 htmlEmitted 编译钩子。参见 API 文档中的 HtmlModulesPlugin.getCompilationHooks。
experiments.lazyCompilation
仅在入口点和动态 import 被使用时才编译它们。它既可以用于 Web,也可以用于 Node.js。
-
类型
-
boolean -
objectts{ // 定义自定义后端 backend?: (( compiler: Compiler, callback: (err?: Error, api?: BackendApi) => void ) => void) | ((compiler: Compiler) => Promise<BackendApi>) | { /** * 自定义客户端。 */ client?: string; /** * 指定服务器监听的位置。 */ listen?: number | ListenOptions | ((server: Server) => void); /** * 指定客户端用于连接服务器的协议。 */ protocol?: "http" | "https"; /** * 指定如何处理 EventSource 请求的服务器。 */ server?: ServerOptionsImport | ServerOptionsHttps | (() => Server); }, entries?: boolean, imports?: boolean, test?: string | RegExp | ((module: Module) => boolean) }backend:自定义后端。entries:为入口启用懒编译。imports:为动态导入启用懒编译。 test:指定哪些导入的模块应该被懒编译。
-
-
可用版本:5.17.0+
-
示例 1:
jsexport default { // … experiments: { lazyCompilation: true, }, }; -
示例 2:
jsexport default { // … experiments: { lazyCompilation: { // 为动态导入禁用懒编译 imports: false, // 为入口禁用懒编译 entries: false, // 不懒编译 moduleB test: (module) => !/moduleB/.test(module.nameForCondition()), }, }, };
experiments.outputModule
boolean
启用后,webpack 将尽可能输出 ECMAScript 模块语法。例如,使用 import() 加载 chunk,使用 ESM 导出暴露 chunk 数据等。
js
export default {
experiments: {
outputModule: true,
},
};
experiments.typescript
启用原生 TypeScript 支持。开启该标志后,webpack 可以直接编译 .ts、.cts 和 .mts 文件(以及匹配的 data:text/typescript 和 data:application/typescript 数据 URI),无需任何外部 loader。在底层,它调用 Node.js 内置的 module.stripTypeScriptTypes。
- 类型:
boolean | 'auto' - 默认值:
false,自 webpack 5.109.0 起为'auto'
自 webpack 5.109.0 起,该选项默认为 'auto':当运行的 Node.js 提供 module.stripTypeScriptTypes(>= 22.6)且 module.rules 中没有带 loader(例如 ts-loader、swc-loader)的规则匹配 .ts/.mts/.cts 文件时,启用内置 TypeScript 支持。experiments.futureDefaults 会将其解析为 true。
W> 需要 Node.js >= 22.6 才能使用稳定的 module.stripTypeScriptTypes API。
js
export default {
experiments: {
typescript: true,
},
entry: "./src/index.ts",
};
启用该标志还会配置一些合理的默认值:.ts / .cts / .mts 的默认规则、将 .ts 添加到扩展名解析中(在 .js 之前)、extensionAlias 使得 import "./foo.js" 也会尝试 ./foo.ts(以及 .cjs / .mjs → .cts / .mts)、tsconfig.json 解析,以及 "typescript" 条件导出键,以便 monorepo 包可以通过 package.json#exports 发布 .ts 源码。
W> 该转换仅执行类型擦除。它不会进行类型检查,也不处理 JSX / .tsx 或不可擦除的 TypeScript 语法(enum、带有运行时成员的 namespace、参数属性构造函数、export =、装饰器元数据)。这些与 TypeScript 在 erasableSyntaxOnly tsconfig 选项中强制执行的约束相同。
对于类型检查,请将该标志与 tsc --noEmit 或 fork-ts-checker-webpack-plugin 配合使用。对于 JSX 或不可擦除的 TypeScript 语法,请继续使用 ts-loader 或 swc-loader。
webpack 仓库提供了两个参考示例:
examples/typescript用于内置的experiments.typescript配置。examples/typescript-non-erasable用于在需要不可擦除语法时回退到ts-loader。
帮助我们改进文档
发现翻译问题或内容错误?请告诉我们。
