vite-plugin-externals
raw JSON → 0.6.2 verified Sat Apr 25 auth: no javascript
A Vite plugin that converts import statements into global variable lookups (window['Lib']), replicating Webpack's externals functionality for production builds. Version 0.6.2 requires Vite >=2.0.0 and Node ^14.18.0 || >=16.0.0. Unlike manual Rollup externals, this plugin transforms source code at the JS level, preserving static analysis. Released under MIT, with occasional updates. Key differentiator: supports deeply chained global paths (e.g., window['React']['lazy']) and works on JSX/TSX files after SFC transformation. Does not affect SSR by default; CJS/SSR users need separate handling.
Common errors
error Cannot find module 'vite-plugin-externals' ↓
cause Package not installed or ESM-only import used in CJS context without proper module resolution.
fix
Run 'npm install vite-plugin-externals --save-dev' and ensure your project is ESM (package.json has "type": "module" or use .mjs files).
error The plugin 'vite:externals' has been applied twice. ↓
cause Multiple instances of the plugin in the same plugins array.
fix
Ensure you only call viteExternalsPlugin() once in the plugins list.
error Unexpected token: keyword 'const' ↓
cause Plugin is transforming files before SFC compilation (e.g., .vue files still contain template code).
fix
Reorder plugins so that viteExternalsPlugin comes after @vitejs/plugin-vue.
error window is not defined ↓
cause The transformed code references window, which is not available in SSR/Node environments.
fix
Disable the plugin for SSR or set useWindow: false (but only if module names have no special characters).
error Uncaught TypeError: Failed to resolve module specifier 'react' ↓
cause Externals mapping is missing or incorrectly configured, so the import is not replaced.
fix
Check that the keys in viteExternalsPlugin options exactly match the import source string (e.g., 'react' not 'React').
Warnings
gotcha Plugin must be placed after SFC transformers (e.g., @vitejs/plugin-vue) because it only operates on JavaScript code, not raw SFC files. ↓
fix Ensure viteExternalsPlugin is listed after Vue/Svelte/etc. plugins in the plugins array.
breaking By default, the plugin does not transform files in node_modules. If you need to externals from node_modules, you must provide a custom filter function. ↓
fix Override the filter option to return true for node_modules paths.
gotcha Using production builds of libraries (e.g., vue.global.prod.js) in dev mode can break HMR. The plugin does not automatically detect this. ↓
fix Set disableInServe: true or load development versions during serve.
gotcha Special characters in module names (e.g., '@scope/pkg') cause runtime errors when useWindow is false, because the variable name would be invalid. ↓
fix Keep useWindow: true (default) or avoid modules with slashes.
deprecated The filter callback signature does not include a third argument in older versions (before 0.5). Check version compatibility if using SSR. ↓
fix Upgrade to >=0.5.0 or adjust filter to ignore the ssr argument.
gotcha Plugin does not work for SSR or CJS environments by default; only transforms ESM-like imports for browser usage. ↓
fix For SSR, use separate configuration (e.g., disable the plugin or handle externals via Rollup options).
Install
npm install vite-plugin-externals yarn add vite-plugin-externals pnpm add vite-plugin-externals Imports
- viteExternalsPlugin wrong
const viteExternalsPlugin = require('vite-plugin-externals')correctimport { viteExternalsPlugin } from 'vite-plugin-externals' - default export (none) wrong
import viteExternalsPlugin from 'vite-plugin-externals'correctimport { viteExternalsPlugin } from 'vite-plugin-externals' - type definitions wrong
import { ViteExternalsOptions } from 'vite-plugin-externals'correctimport type { ViteExternalsOptions } from 'vite-plugin-externals'
Quickstart
// vite.config.js
import { defineConfig } from 'vite';
import { viteExternalsPlugin } from 'vite-plugin-externals';
export default defineConfig({
plugins: [
viteExternalsPlugin({
vue: 'Vue',
react: 'React',
'react-dom': 'ReactDOM',
lazy: ['React', 'lazy']
}, {
disableInServe: true,
useWindow: true,
filter: (code, id, ssr) => {
// Exclude node_modules and non-js files
if (id.includes('node_modules')) return false;
if (!/\.[jt]sx?$/.test(id)) return false;
return true;
}
})
]
});