@vitejs/plugin-legacy 插件说明
@vitejs/plugin-legacy 插件说明
Vite 默认的浏览器支持目标是原生 ESM 动态导入和 import.meta。本插件用于在生产构建中为不支持这些特性的旧浏览器提供兼容支持。
默认情况下,该插件将:
- 为最终打包产物中的每个 chunk 生成对应的旧版 chunk,使用 @babel/preset-env 进行转换,并以 SystemJS 模块形式输出(仍支持代码分割)。
- 生成一个 polyfill chunk,其中包含 SystemJS 运行时,以及根据指定的浏览器目标和包中的实际使用情况所需的必要 polyfills。
- 在生成的 HTML 中注入
<script nomodule>标签,仅在缺乏广泛可用特性支持的浏览器中有条件地加载 polyfills 和旧版 bundle。 - 注入
import.meta.env.LEGACY环境变量,该变量仅在旧版生产构建中为true,其他情况下均为false。
使用方法
js
// vite.config.js
import legacy from '@vitejs/plugin-legacy'
export default {
plugins: [
legacy({
targets: ['defaults', 'not IE 11'],
}),
],
}
当使用低于 8.1.4 的 Vite 版本,或
build.minify被显式设置为terser时,需要安装 Terser 用于代码压缩。
shnpm add -D terser
配置选项
targets
-
类型:
string | string[] | { [key: string]: string } -
默认值:
'last 2 versions and not dead, > 0.3%, Firefox ESR'在渲染旧版 chunks 时,该值会传递给
@babel/preset-env。该查询条件同样兼容 Browserslist。更多详情请参阅 Browserslist 最佳实践。
如果未设置,plugin-legacy 将加载 browserslist 配置源,然后回退到默认值。
modernTargets
-
类型:
string | string[] -
默认值:
'edge>=105, firefox>=106, chrome>=105, safari>=16.4, chromeAndroid>=105, iOS>=16.4'在收集现代 chunks 的 polyfills 时,该值会传递给
@babel/preset-env。此处设置的值将覆盖build.target选项。该查询条件同样兼容 Browserslist。更多详情请参阅 Browserslist 最佳实践。
如果未设置,plugin-legacy 将回退到默认值。
注意:除非
renderLegacyChunks设置为false,否则不应设置此选项。
polyfills
-
类型:
boolean | string[] -
默认值:
true默认情况下,会根据目标浏览器范围以及最终包中的实际使用情况(通过
@babel/preset-env的useBuiltIns: 'usage'检测)生成 polyfills chunk。设置为字符串列表可以显式控制包含哪些 polyfills。详情请参阅 Polyfill 说明符。
设置为
false可避免生成 polyfills 并自行处理(仍会生成带有语法转换的旧版 chunks)。
additionalLegacyPolyfills
-
类型:
string[]向旧版 polyfills chunk 添加自定义导入。由于基于使用情况的 polyfill 检测仅涵盖 ES 语言特性,因此可能需要使用此选项手动指定额外的 DOM API polyfills。
additionalModernPolyfills
-
类型:
string[]向现代 polyfills chunk 添加自定义导入。由于基于使用情况的 polyfill 检测仅涵盖 ES 语言特性,因此可能需要使用此选项手动指定额外的 DOM API polyfills。
modernPolyfills
-
类型:
boolean | string[] -
默认值:
false默认为
false。启用此选项将为现代构建(针对支持广泛可用特性的浏览器)生成单独的 polyfills chunk。设置为字符串列表可以显式控制包含哪些 polyfills。详情请参阅 Polyfill 说明符。
如果未设置
modernTargets,则不建议使用true值(即自动检测模式),因为core-js@3包含了大量前沿特性,在 polyfill 包含方面相当激进。即使针对原生 ESM 支持,它也会注入 15kb 的 polyfills!如果你不强烈依赖前沿的运行时特性,那么避免在现代构建中使用 polyfills 并不难。或者,可以考虑设置
modernTargets,或使用按需服务(如 https://cdnjs.cloudflare.com/polyfill/)仅根据实际浏览器用户代理注入必要的 polyfills(大多数现代浏览器根本不需要!)。
renderLegacyChunks
-
类型:
boolean -
默认值:
true设置为
false可禁用旧版 chunks。这仅在配合modernPolyfills使用时有用,本质上允许你仅使用该插件为现代构建注入 polyfills:jsimport legacy from '@vitejs/plugin-legacy' export default { plugins: [ legacy({ modernPolyfills: [/* ... */], renderLegacyChunks: false, }), ], }
externalSystemJS
-
类型:
boolean -
默认值:
false默认为
false。启用此选项将在 polyfills-legacy chunk 中排除systemjs/dist/s.min.js。
renderModernChunks
-
类型:
boolean -
默认值:
true设置为
false可仅输出支持所有目标浏览器的旧版 bundles。这在通过
file:协议在本地运行项目时也很有用,因为使用type="module"加载现代 chunks 可能会触发 CORS 限制。为避免此问题,只需将renderModernChunks设置为false,即可专门使用旧版 chunks。
支持 ESM 但不支持广泛可用特性的浏览器
旧版插件提供了一种方式:在现代构建中原生使用广泛可用的特性,同时在具有原生 ESM 但不支持这些特性的浏览器(如旧版 Edge)中回退到旧版构建。该功能通过注入运行时检查并在需要时使用 SystemJS 运行时加载旧版 bundle 来实现。这存在以下缺点:
- 所有支持 ESM 的浏览器都会下载现代 bundle
- 在不支持这些特性的浏览器中,现代 bundle 会抛出错误
以下特性被视为广泛可用的:
- 动态导入(dynamic import)
- 异步生成器(async generator)
import.meta.resolve
Polyfill 说明符
polyfills 和 modernPolyfills 的 polyfill 说明符字符串可以是以下任意一种:
- 任何
core-js3 子导入路径——例如es/map将导入core-js/es/map - 任何单独的
core-js3 模块——例如es.array.iterator将导入core-js/modules/es.array.iterator.js
示例
js
import legacy from '@vitejs/plugin-legacy'
export default {
plugins: [
legacy({
polyfills: ['es.promise.finally', 'es/map', 'es/set'],
modernPolyfills: ['es.promise.finally'],
}),
],
}
内容安全策略(CSP)
旧版插件需要内联脚本来实现 Safari 10.1 nomodule 修复、SystemJS 初始化和动态导入回退。如果你有严格的内容安全策略要求,则需要将相应的哈希值添加到你的 script-src 列表中。
可以通过以下方式获取哈希值(不带 sha256- 前缀):
js
import { cspHashes } from '@vitejs/plugin-legacy'
当前值为:
sha256-MS6/3FCg4WjP9gwgaBGwLpRCY6fZBgwmhVCdrPrNf3E=sha256-tQjf8gvb2ROOMapIxFvFAYBeUJ0v1HCbOcSmDNXGtDo=sha256-w36slEqa9euNKxfvkw+LLGsDIr++3rsZXpZxtmRh8Aw=sha256-+5XkZFazzJo8n0iOP4ti/cLCMUudTf//Mzkb7xNPXIc=
注意,这些值可能在次版本之间发生变化。因此,我们建议从导出的 cspHashes 变量中生成 CSP 头。如果你手动复制这些值,则应使用 ~ 锁定次版本。
当使用 regenerator-runtime polyfill 时,它会尝试使用 globalThis 对象来注册自身。如果 globalThis 不可用(它是相当新的特性,支持范围不够广泛,包括 IE 11 也不支持),它会尝试执行动态的 Function(...) 调用,这会违反 CSP。为避免在缺少 globalThis 时进行动态 eval,请考虑将 core-js/proposals/global-this 添加到 additionalLegacyPolyfills 中以定义该对象。
参考链接
帮助我们改进文档
发现翻译问题或内容错误?请告诉我们。
