知海

@vitejs/plugin-legacy 插件说明

vite-main模板、包与插件

@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 用于代码压缩。

sh 复制代码
npm add -D terser

配置选项

targets

modernTargets

polyfills

  • 类型: boolean | string[]

  • 默认值: true

    默认情况下,会根据目标浏览器范围以及最终包中的实际使用情况(通过 @babel/preset-envuseBuiltIns: '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:

    js 复制代码
    import 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 说明符

polyfillsmodernPolyfills 的 polyfill 说明符字符串可以是以下任意一种:

示例

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 中以定义该对象。

参考链接

帮助我们改进文档

发现翻译问题或内容错误?请告诉我们。