Vite plugin to support legacy browsers that do not support native ESM
—
Advanced polyfill detection and management system for automatic browser compatibility polyfills.
Analyzes JavaScript/TypeScript code to automatically detect required polyfills based on browser targets.
/**
* Analyzes code to detect required polyfills using Babel preset-env
* @param code - JavaScript/TypeScript code to analyze for polyfill requirements
* @param targets - Browser targets (browserslist format) for polyfill detection
* @param assumptions - Babel assumptions for code analysis optimization
* @param list - Set to populate with discovered polyfill import paths
* @returns Promise that resolves when polyfill detection is complete
*/
function detectPolyfills(
code: string,
targets: any,
assumptions: Record<string, boolean>,
list: Set<string>
): Promise<void>;Usage Examples:
import { detectPolyfills } from '@vitejs/plugin-legacy';
// Detect polyfills for specific code
const polyfills = new Set<string>();
await detectPolyfills(
`
const promise = Promise.resolve();
const array = [1, 2, 3].includes(2);
const map = new Map();
`,
['> 1%', 'last 2 versions'],
{},
polyfills
);
console.log(polyfills);
// Set containing core-js imports like:
// 'core-js/modules/es.promise.js'
// 'core-js/modules/es.array.includes.js'
// 'core-js/modules/es.map.js'Different formats for specifying polyfills in plugin configuration.
type PolyfillSpecifier = string;
/**
* Polyfill specifiers can be:
* - core-js sub-import paths: 'es/map' -> 'core-js/es/map'
* - Individual core-js modules: 'es.array.iterator' -> 'core-js/modules/es.array.iterator.js'
* - Direct module paths: 'regenerator-runtime/runtime'
*/Examples:
legacy({
// Different polyfill specification formats
polyfills: [
'es.promise.finally', // Individual module
'es/map', // Sub-import path
'es/set', // Sub-import path
'regenerator', // Special case for regenerator-runtime
],
additionalLegacyPolyfills: [
'intersection-observer', // Third-party polyfill
'custom-polyfill', // Custom polyfill
],
modernPolyfills: [
'es.promise.finally', // Only newer features for modern builds
],
});Configuration options for automatic polyfill detection behavior.
interface AutomaticPolyfillOptions {
/** Enable automatic polyfill detection based on code usage */
polyfills: true;
/** Browser targets for polyfill requirement analysis */
targets?: string | string[] | Record<string, string>;
/** Modern browser targets for modern polyfill detection */
modernTargets?: string | string[];
/** Enable modern polyfill detection (requires modernTargets or uses defaults) */
modernPolyfills?: boolean;
}Usage Examples:
// Full automatic detection
legacy({
polyfills: true,
modernPolyfills: true,
targets: ['> 0.5%', 'last 2 versions'],
modernTargets: ['supports es6-module'],
});
// Legacy-only automatic detection
legacy({
polyfills: true,
modernPolyfills: false,
targets: ['IE 11', 'Chrome >= 49'],
});Explicit polyfill specification for fine-grained control.
interface ManualPolyfillOptions {
/** Specific polyfills to include (disables automatic detection) */
polyfills: string[];
/** Additional polyfills beyond automatic detection */
additionalLegacyPolyfills?: string[];
/** Additional modern polyfills beyond automatic detection */
additionalModernPolyfills?: string[];
/** Specific modern polyfills (disables automatic modern detection) */
modernPolyfills?: string[];
}Usage Examples:
// Completely manual polyfill control
legacy({
polyfills: [
'core-js/modules/es.promise.js',
'core-js/modules/es.array.includes.js',
'regenerator-runtime/runtime.js',
],
modernPolyfills: [
'core-js/modules/es.promise.finally.js',
],
});
// Hybrid approach: automatic + additional
legacy({
polyfills: true, // Automatic detection
additionalLegacyPolyfills: [
'intersection-observer',
'resize-observer-polyfill',
],
additionalModernPolyfills: [
'core-js/proposals/global-this',
],
});Options to disable polyfill generation entirely.
interface DisabledPolyfillOptions {
/** Disable all polyfill generation */
polyfills: false;
/** Modern polyfills still configurable when legacy polyfills disabled */
modernPolyfills?: boolean | string[];
}Usage Examples:
// No polyfills (syntax transformation only)
legacy({
polyfills: false,
targets: ['> 1%', 'last 2 versions'],
});
// Legacy disabled, modern enabled
legacy({
polyfills: false,
modernPolyfills: ['es.promise.finally'],
renderLegacyChunks: false,
});The plugin integrates with core-js for comprehensive polyfill coverage.
/**
* Supported polyfill import patterns:
* - 'es/promise' -> 'core-js/es/promise'
* - 'es.promise.finally' -> 'core-js/modules/es.promise.finally.js'
* - 'regenerator' -> 'regenerator-runtime/runtime.js'
*/
type CoreJSPolyfillPath = string;Common Core-js Polyfills:
legacy({
polyfills: [
// ES6+ Features
'es.promise',
'es.promise.finally',
'es.array.includes',
'es.array.find',
'es.array.flat',
'es.object.assign',
'es.string.includes',
// Collections
'es.map',
'es.set',
'es.weak-map',
'es.weak-set',
// Async/Iterator support
'regenerator',
'es.symbol.async-iterator',
// Newer proposals
'es.string.replace-all',
'es.promise.all-settled',
],
});Install with Tessl CLI
npx tessl i tessl/npm-vitejs--plugin-legacy