Home

Awesome

vite-plugin-legacy-swc

npm

Provides legacy browsers support for the production build with SWC.

This package is intended to replace @vitejs/plugin-legacy in performance-sensitive situations. It is basically an implementation of vitejs/vite#4105.

As for performance, for reference, the results of my tests on a huge private project (with { modernPolyfills: true }) are as follows:

Without legacy browsers supportWith @vitejs/plugin-legacyWith vite-plugin-legacy-swc
CPU Time146.45s697.82s295.04s
JS Asset Size*9.5M22M21M
JS Asset Size Without Legacy Chunks9.5M9.6M9.6M

Compared to @vitejs/plugin-legacy, vite-plugin-legacy-swc saves 58% of time and 4% of JS asset size.

* In my current tests, @vitejs/plugin-legacy does not generate source maps for legacy chunks correctly, so the asset size statistics exclude the source maps.


Vite's default browser support baseline is Native ESM, native ESM dynamic import, and import.meta. This plugin provides support for legacy browsers that do not support those features when building for production.

By default, this plugin will:

Usage

// vite.config.js
import legacy from 'vite-plugin-legacy-swc'

export default {
  plugins: [
    legacy({
      targets: ['defaults', 'not IE 11'],
    }),
  ],
}

Options

targets

modernTargets

polyfills

additionalLegacyPolyfills

additionalModernPolyfills

modernPolyfills

renderLegacyChunks

externalSystemJS

renderModernChunks

Browsers that supports ESM but does not support widely-available features

The legacy plugin offers a way to use widely-available features natively in the modern build, while falling back to the legacy build in browsers with native ESM but without those features supported (e.g. Legacy Edge). This feature works by injecting a runtime check and loading the legacy bundle with SystemJs runtime if needed. There are the following drawbacks:

The following syntax are considered as widely-available:

Polyfill Specifiers

Polyfill specifier strings for polyfills and modernPolyfills can be either of the following:

Example

import legacy from 'vite-plugin-legacy-swc'

export default {
  plugins: [
    legacy({
      polyfills: ['es.promise.finally', 'es/map', 'es/set'],
      modernPolyfills: ['es.promise.finally'],
    }),
  ],
}

Content Security Policy

The legacy plugin requires inline scripts for Safari 10.1 nomodule fix, SystemJS initialization, and dynamic import fallback. If you have a strict CSP policy requirement, you will need to add the corresponding hashes to your script-src list.

The hash values (without the sha256- prefix) can be retrieved via:

import { cspHashes } from 'vite-plugin-legacy-swc'

The current values are:

<!-- Run `node --input-type=module -e "import {cspHashes} from 'vite-plugin-legacy-swc'; console.log(cspHashes.map(h => 'sha256-'+h))"` to retrieve the value. -->

Note that these values could change between minor versions. Thus, we recommend generating the CSP header from the exported cspHashes variable. If you copy the values manually, then you should pin the minor version using ~.

When using the regenerator-runtime polyfill, it will attempt to use the globalThis object to register itself. If globalThis is not available (it is fairly new and not widely supported, including IE 11), it attempts to perform dynamic Function(...) call which violates the CSP. To avoid dynamic eval in the absence of globalThis consider adding core-js/proposals/global-this to additionalLegacyPolyfills to define it.

References