This Babel plugin transforms ES2015 (ES6) module syntax into CommonJS format, enabling modern JavaScript modules to work in Node.js environments that require CommonJS. The plugin handles import and export statements, converting them to require() calls and module.exports assignments while preserving module semantics.
npm install --save-dev @babel/plugin-transform-modules-commonjsimport pluginTransformModulesCommonJS, {
defineCommonJSHook,
lazyImportsHook,
transformDynamicImport
} from "@babel/plugin-transform-modules-commonjs";For CommonJS:
const pluginTransformModulesCommonJS = require("@babel/plugin-transform-modules-commonjs");
const {
defineCommonJSHook,
lazyImportsHook,
transformDynamicImport
} = require("@babel/plugin-transform-modules-commonjs");// babel.config.js
module.exports = {
plugins: ["@babel/plugin-transform-modules-commonjs"]
};// babel.config.js
module.exports = {
plugins: [
["@babel/plugin-transform-modules-commonjs", {
"allowCommonJSExports": true,
"allowTopLevelThis": false,
"importInterop": "babel",
"lazy": true,
"loose": false,
"mjsStrictNamespace": false,
"noInterop": false,
"strict": false,
"strictMode": false,
"strictNamespace": false
}]
]
};Input (ES6 modules):
import foo from "./foo";
import { bar, baz } from "./bar";
export { fizz } from "./fizz";
export default buzz;Output (CommonJS):
var _foo = require("./foo");
var _bar = require("./bar");
var _fizz = require("./fizz");
exports.fizz = _fizz.fizz;
exports.default = buzz;Main plugin factory function that creates the Babel plugin using Babel's declare helper.
/**
* Creates a Babel plugin for transforming ES modules to CommonJS
* Uses Babel's declare() helper for plugin creation
*/
declare const pluginTransformModulesCommonJS: PluginObj<PluginPass>;
export default pluginTransformModulesCommonJS;
interface PluginObj<P = PluginPass> {
name?: string;
manipulateOptions?(opts: any, parserOpts: any): void;
pre?(this: P, file: BabelFile): void;
visitor: Visitor<P>;
post?(this: P, file: BabelFile): void;
inherits?: any;
}Plugin configuration interface defining all available options.
interface Options extends PluginOptions {
/** Allow CommonJS exports (default: true) */
allowCommonJSExports?: boolean;
/** Allow top-level 'this' (default: undefined) */
allowTopLevelThis?: boolean;
/** Import interop configuration */
importInterop?: ImportInterop;
/** Lazy import configuration - can be boolean, string array, or function */
lazy?: Lazy;
/** Enable loose mode transformations (default: false) */
loose?: boolean;
/** Strict namespace for .mjs files (defaults to strictNamespace) */
mjsStrictNamespace?: boolean;
/** Disable interop helpers (default: false) */
noInterop?: boolean;
/** Enable strict mode (default: undefined) */
strict?: boolean;
/** Enable strict mode (default: undefined) */
strictMode?: boolean;
/** Strict namespace handling (default: false) */
strictNamespace?: boolean;
}
type ImportInterop = "none" | "babel" | "node" | ((source: string, filename?: string) => "none" | "babel" | "node");
type Lazy = boolean | string[] | ((source: string) => boolean);
interface PluginOptions {
moduleId?: string;
moduleIds?: boolean;
getModuleId?: (moduleName: string) => string | null | undefined;
moduleRoot?: string;
}Advanced customization system for plugin behavior. Exported as a named export.
/**
* Registers a CommonJS transformation hook for customization
* @param file - Babel file object
* @param hook - Hook implementation
*/
export function defineCommonJSHook(file: File, hook: CommonJSHook): void;
interface CommonJSHook {
/** Hook name identifier */
name: string;
/** Hook version */
version: string;
/** Optional function to wrap reference expressions */
wrapReference?(ref: Expression, payload: unknown): CallExpression | null;
/** Optional function to customize require() call wrapping */
buildRequireWrapper?(
name: string,
init: Expression,
payload: unknown,
referenced: boolean
): Statement | false | null;
/** Optional function to get wrapper payload data */
getWrapperPayload?(
source: string,
metadata: SourceModuleMetadata,
importNodes: Node[]
): unknown;
}Built-in lazy loading functionality for imports. Available as an exported function.
/**
* Creates a hook for lazy import handling
* @param lazy - Lazy configuration (boolean, string array, or function)
* @returns CommonJS hook for lazy imports
*/
export function lazyImportsHook(lazy: Lazy): CommonJSHook;Support for transforming dynamic import expressions. Available as an exported function.
/**
* Transforms dynamic import expressions to require calls
* @param path - AST node path for the import expression
* @param noInterop - Whether to disable interop helpers
* @param file - Babel file object
*/
export function transformDynamicImport(
path: NodePath<CallExpression | ImportExpression>,
noInterop: boolean,
file: File
): void;All Babel AST and plugin-related types used in the API.
// Core Babel types from @babel/core
interface File {
ast: Node;
code: string | null;
map: SourceMap | null;
opts: BabelFileOptions;
hub: Hub;
metadata: { [key: string]: any };
path: NodePath;
scope: Scope;
addHelper(name: string): Expression;
get(key: string): any;
set(key: string, value: any): void;
has(key: string): boolean;
}
interface Node {
type: string;
loc?: SourceLocation | null;
leadingComments?: Comment[] | null;
innerComments?: Comment[] | null;
trailingComments?: Comment[] | null;
start?: number | null;
end?: number | null;
}
interface Expression extends Node {
// Base interface for all expression nodes
}
interface CallExpression extends Expression {
type: "CallExpression";
callee: Expression;
arguments: Array<Expression | SpreadElement>;
}
interface ImportExpression extends Expression {
type: "ImportExpression";
source: Expression;
}
interface Statement extends Node {
// Base interface for all statement nodes
}
interface NodePath<T = Node> {
node: T;
parent: Node;
parentPath: NodePath;
scope: Scope;
hub: Hub;
isCallExpression(): boolean;
isImportExpression(): boolean;
replaceWith(replacement: Node): void;
}
interface SourceModuleMetadata {
name: string;
loc: SourceLocation | undefined | null;
interop: InteropType;
imports: Map<string, string>;
importsNamespace: Set<string>;
reexports: Map<string, string>;
reexportNamespace: Set<string>;
reexportAll: null | {
loc: SourceLocation | undefined | null;
};
wrap?: unknown;
referenced: boolean;
}
interface Scope {
path: NodePath;
block: Node;
parent: Scope | null;
hub: Hub;
uid: number;
rename(oldName: string, newName?: string): void;
getBinding(name: string): Binding | undefined;
}
type InteropType = "default" | "namespace" | "node-default" | "node-namespace" | "none";
interface SourceLocation {
start: Position;
end: Position;
}
interface Position {
line: number;
column: number;
}
// Additional required types
interface Hub {
file: File;
getCode(): string;
getScope(): Scope;
}
interface Binding {
identifier: Node;
scope: Scope;
path: NodePath;
kind: "const" | "let" | "var" | "hoisted" | "param" | "local" | "module";
referenced: boolean;
referencePaths: NodePath[];
}
interface SpreadElement extends Node {
type: "SpreadElement";
argument: Expression;
}
interface Comment {
type: "CommentBlock" | "CommentLine";
value: string;
start?: number;
end?: number;
loc?: SourceLocation;
}
interface SourceMap {
version: number;
sources: string[];
names: string[];
mappings: string;
file?: string;
sourceRoot?: string;
sourcesContent?: string[];
}
interface BabelFileOptions {
filename?: string;
filenameRelative?: string;
sourceType?: "script" | "module" | "unambiguous";
inputSourceMap?: any;
[key: string]: any;
}
type VisitorFunction = (path: NodePath, state?: any) => void;
interface Visitor<P = PluginPass> {
[key: string]: VisitorFunction | {
enter?: VisitorFunction;
exit?: VisitorFunction;
};
}
interface PluginPass {
key?: string;
file: BabelFile;
opts: any;
cwd: string;
filename?: string;
}
interface BabelFile extends File {
// Babel file interface extending base File
}// Minimal setup
{
"plugins": ["@babel/plugin-transform-modules-commonjs"]
}// Strict namespace handling
{
"plugins": [
["@babel/plugin-transform-modules-commonjs", {
"strictNamespace": true,
"mjsStrictNamespace": true
}]
]
}// Lazy load specific modules
{
"plugins": [
["@babel/plugin-transform-modules-commonjs", {
"lazy": ["lodash", "axios"]
}]
]
}
// Lazy load all external modules
{
"plugins": [
["@babel/plugin-transform-modules-commonjs", {
"lazy": true
}]
]
}
// Custom lazy loading logic
{
"plugins": [
["@babel/plugin-transform-modules-commonjs", {
"lazy": (source) => source.startsWith("@company/")
}]
]
}// Enable loose transformations for smaller output
{
"plugins": [
["@babel/plugin-transform-modules-commonjs", {
"loose": true
}]
]
}// Full configuration example
{
"plugins": [
["@babel/plugin-transform-modules-commonjs", {
"allowCommonJSExports": true,
"allowTopLevelThis": false,
"importInterop": "babel",
"lazy": false,
"loose": false,
"mjsStrictNamespace": false,
"noInterop": false,
"strict": undefined,
"strictMode": undefined,
"strictNamespace": false
}]
]
}The plugin validates configuration options and throws descriptive errors:
lazy is not boolean, string array, or functionstrictNamespace is not boolean or undefinedmjsStrictNamespace is not boolean or undefined