vite-legacy-interop
raw JSON → 1.0.4 verified Mon Apr 27 auth: no javascript
A Vite 8 plugin that wraps legacy CJS subpath imports in ESM-compatible virtual modules to prevent runtime interop errors. Current version 1.0.4, actively maintained. Designed for Vite 8 and Rolldown, it intercepts imports like `legacy-lib/lib/Button` and replaces them with virtual ESM wrappers that handle CJS-to-ESM interop, solving `SyntaxError` and `ReferenceError` at runtime. Differentiators: targeted at Vite 8 with Rolldown, supports multiple libraries and nested subpaths, minimal configuration, includes debug logging.
Common errors
error SyntaxError: The requested module 'legacy-lib/lib/Button' does not provide an export named 'default' ↓
cause Rolldown does not perform CJS-to-ESM interop for subpath imports.
fix
Install and configure vite-legacy-interop with 'legacy-lib' in libs.
error ReferenceError: require is not defined ↓
cause Legacy CJS module is emitted as-is in ESM bundle.
fix
Add vite-legacy-interop plugin with the legacy library name.
error Error: The plugin 'vite:legacy-interop' requires Vite >=8.0.0 ↓
cause Attempting to use with older Vite version.
fix
Upgrade Vite to 8.x or remove this plugin.
Warnings
breaking Requires Vite 8.x; incompatible with Vite 7 or earlier. ↓
fix Upgrade to Vite 8 or use alternative plugin for earlier Vite versions.
gotcha Plugin must be placed before other plugins that transform imports. ↓
fix Ensure legacyInterop is first in the plugins array.
deprecated Option 'libDir' default is 'lib'; legacy packages with different directory must specify. ↓
fix Explicitly set 'libDir' if your package uses 'dist' or other paths.
gotcha Virtual module IDs start with '\0legacy-interop:' which may conflict with other plugins. ↓
fix Avoid other plugins using the same namespace prefix.
gotcha Does not handle dynamic imports (import()) or require() calls; only static import statements. ↓
fix Use static imports for legacy CJS subpaths.
Install
npm install vite-legacy-interop yarn add vite-legacy-interop pnpm add vite-legacy-interop Imports
- legacyInterop wrong
import legacyInterop from 'vite-legacy-interop'correctimport { legacyInterop } from 'vite-legacy-interop' - LegacyInteropOptions wrong
import { LegacyInteropOptions } from 'vite-legacy-interop'correctimport type { LegacyInteropOptions } from 'vite-legacy-interop' - LibConfig wrong
import { LibConfig } from 'vite-legacy-interop'correctimport type { LibConfig } from 'vite-legacy-interop'
Quickstart
// vite.config.ts
import { defineConfig } from 'vite';
import { legacyInterop } from 'vite-legacy-interop';
export default defineConfig({
plugins: [
legacyInterop({
libs: ['legacy-lib'],
showLog: true,
apply: 'build',
}),
],
});
// Now imports like:
// import Button from 'legacy-lib/lib/Button'
// are transparently wrapped in ESM interop modules.