Vite plugin to support legacy browsers that do not support native ESM
—
Content Security Policy configuration for @vitejs/plugin-legacy inline scripts.
Pre-computed SHA-256 hash values for all inline scripts generated by the plugin, required for strict CSP policies.
/**
* Array of SHA-256 hash values for inline scripts used by the plugin
* These hashes should be added to your CSP script-src directive
* @readonly
*/
const cspHashes: string[];Usage Examples:
import legacy, { cspHashes } from '@vitejs/plugin-legacy';
// Use in CSP header generation
const cspHashes = [
'sha256-MS6/3FCg4WjP9gwgaBGwLpRCY6fZBgwmhVCdrPrNf3E=',
'sha256-tQjf8gvb2ROOMapIxFvFAYBeUJ0v1HCbOcSmDNXGtDo=',
'sha256-ZxAi3a7m9Mzbc+Z1LGuCCK5Xee6reDkEPRas66H9KSo=',
'sha256-+5XkZFazzJo8n0iOP4ti/cLCMUudTf//Mzkb7xNPXIc=',
];
// Generate CSP header
const cspHeader = `script-src 'self' ${cspHashes.map(h => `'${h}'`).join(' ')}`;Generate CSP headers dynamically using the exported hash values.
Implementation Example:
import { cspHashes } from '@vitejs/plugin-legacy';
// Helper function for generating CSP headers (not exported by plugin)
function generateCSPHeader(additionalSources: string[] = []): string {
const baseSources = ["'self'"];
const hashSources = cspHashes.map(hash => `'sha256-${hash}'`);
const allSources = [...baseSources, ...hashSources, ...additionalSources];
return `script-src ${allSources.join(' ')}`;
}
// Usage in server middleware
app.use((req, res, next) => {
const cspHeader = generateCSPHeader(["'unsafe-eval'"]);
res.setHeader('Content-Security-Policy', cspHeader);
next();
});The plugin generates several types of inline scripts that require CSP allowlisting. These are internal to the plugin and not directly exported, but understanding them helps with CSP configuration.
Complete CSP policy examples for different security requirements.
Strict CSP (Recommended):
<meta http-equiv="Content-Security-Policy" content="
default-src 'self';
script-src 'self'
'sha256-MS6/3FCg4WjP9gwgaBGwLpRCY6fZBgwmhVCdrPrNf3E='
'sha256-tQjf8gvb2ROOMapIxFvFAYBeUJ0v1HCbOcSmDNXGtDo='
'sha256-ZxAi3a7m9Mzbc+Z1LGuCCK5Xee6reDkEPRas66H9KSo='
'sha256-+5XkZFazzJo8n0iOP4ti/cLCMUudTf//Mzkb7xNPXIc=';
style-src 'self' 'unsafe-inline';
img-src 'self' data:;
">Development CSP (Less Strict):
<meta http-equiv="Content-Security-Policy" content="
default-src 'self';
script-src 'self' 'unsafe-eval'
'sha256-MS6/3FCg4WjP9gwgaBGwLpRCY6fZBgwmhVCdrPrNf3E='
'sha256-tQjf8gvb2ROOMapIxFvFAYBeUJ0v1HCbOcSmDNXGtDo='
'sha256-ZxAi3a7m9Mzbc+Z1LGuCCK5Xee6reDkEPRas66H9KSo='
'sha256-+5XkZFazzJo8n0iOP4ti/cLCMUudTf//Mzkb7xNPXIc=';
style-src 'self' 'unsafe-inline';
">CSP hash values may change between plugin versions:
Version Pinning Example:
{
"dependencies": {
"@vitejs/plugin-legacy": "~7.2.1"
}
}Special consideration for regenerator-runtime and globalThis. When using regenerator-runtime polyfill without globalThis support, add core-js globalThis polyfill to prevent CSP violations.
Implementation:
legacy({
additionalLegacyPolyfills: [
// Prevents CSP violations in IE 11 and other browsers without globalThis
'core-js/proposals/global-this',
],
});CSP configuration for different server environments.
Express.js:
import express from 'express';
import { cspHashes } from '@vitejs/plugin-legacy';
const app = express();
app.use((req, res, next) => {
const hashes = cspHashes.map(h => `'sha256-${h}'`).join(' ');
const csp = `script-src 'self' ${hashes}`;
res.setHeader('Content-Security-Policy', csp);
next();
});Nginx:
location / {
add_header Content-Security-Policy "script-src 'self' 'sha256-MS6/3FCg4WjP9gwgaBGwLpRCY6fZBgwmhVCdrPrNf3E=' 'sha256-tQjf8gvb2ROOMapIxFvFAYBeUJ0v1HCbOcSmDNXGtDo=' 'sha256-ZxAi3a7m9Mzbc+Z1LGuCCK5Xee6reDkEPRas66H9KSo=' 'sha256-+5XkZFazzJo8n0iOP4ti/cLCMUudTf//Mzkb7xNPXIc='";
}Install with Tessl CLI
npx tessl i tessl/npm-vitejs--plugin-legacy