docs/builtin-plugins/esm-external-require.md
The esmExternalRequirePlugin is a built-in Rolldown plugin that converts CommonJS require() calls for external dependencies into ESM import statements, ensuring compatibility in environments that don't support the Node.js module API.
:::tip NOTE
This plugin sets resolveId.meta.order to 'pre' to ensure external requires are resolved before other plugins. Additionally, it sets enforce: 'pre' by default for Vite compatibility.
:::
When bundling code with Rolldown, require() calls for external dependencies are not automatically converted to ESM imports to preserve the semantics of require(). While Rolldown injects require function when platform: 'node' is set, it does so by generating code like:
import { createRequire } from 'node:module';
var __require = createRequire(import.meta.url);
However, this approach relies on the Node.js module API, which isn't available in some environments. This approach is also problematic for libraries that are expected to be bundled later, as this code is difficult to be analyzed and transformed by bundlers.
Import and use the plugin from Rolldown's experimental exports:
import { defineConfig } from 'rolldown';
import { esmExternalRequirePlugin } from 'rolldown/plugins';
export default defineConfig({
input: 'src/index.js',
output: {
dir: 'dist',
format: 'esm',
},
plugins: [
esmExternalRequirePlugin({
external: ['react', 'vue', /^node:/],
}),
],
});
externalType: (string | RegExp)[]
Defines which dependencies should be treated as external. When the output format is ESM, their require() calls will be converted to import statements. For non-ESM output formats, the dependencies will be marked as external but the require() calls will remain unchanged.
skipDuplicateCheckType: boolean
Default: false
When enabled, skips checking for duplicate externals between this plugin and the top-level external option. This can improve build performance when you're confident there are no duplicates.
esmExternalRequirePlugin({
external: ['react', 'vue'],
skipDuplicateCheck: true, // Skip duplicate check for better performance
});
By default, the plugin checks if any externals you specify are also configured in the top-level external option. If duplicates are found, you'll see a warning:
Found 2 duplicate external: `react`, `vue`. Remove them from top-level `external` as they're already handled by 'builtin:esm-external-require' plugin.
This helps avoid configuration confusion and ensures the plugin handles ESM require() transforms correctly. You can disable this check by setting skipDuplicateCheck: true if you're confident about your configuration.
Since this plugin changes require() calls to import statements, there are some semantic differences after bundling:
import behavior, not require behavior
import condition is used instead of require conditionrequire() calls, especially for modules with default exports.This plugin intercepts require() calls for dependencies specified in the option and creates virtual facade modules that:
import * as m from '...'module.exports = m for CommonJS compatibilityrequire() with the virtual module referenceFor non-external require() calls, Rolldown automatically wraps them and converts them into ESM imports.
// Input code
const react = require('react');
// Transformed output
const react = require('builtin:esm-external-require-react');
// Virtual module: builtin:esm-external-require-react
import * as m from 'react';
module.exports = m;