Bundling CJS
Rolldown provides first-class support for CommonJS modules. This document explains how Rolldown handles CJS modules and their interoperability with ES modules.
Key Features
Native CJS Support
Rolldown automatically recognizes and processes CommonJS modules without requiring any additional plugins or packages. This native support means:
- No need to install extra dependencies
- Better performance compared to plugin-based solutions
On-demand Execution
Rolldown preserves the on-demand execution semantics of CommonJS modules, which is a key feature of the CommonJS module system. This means modules are only executed when they are actually required.
Here's an example:
// index.js
import { value } from './foo.js';
const getFooExports = () => require('./foo.js');
// foo.js
module.exports = { value: 'foo' };When bundled, it produces:
// #region rolldown:runtime
// ...runtime code
// #endregion
// #region foo.js
var require_foo = __commonJS({
'foo.js'(exports, module) {
module.exports = { value: 'foo' };
},
});
// #endregion
// #region index.js
const getFooExports = () => require_foo();
// #endregionIn this example, the foo.js module won't be executed until getFooExports() is called, maintaining the lazy-loading behavior of CommonJS.
ESM/CJS Interoperability
Rolldown provides seamless interoperability between ES modules and CommonJS modules.
Example of ESM importing from CJS:
// index.js
import { value } from './foo.js';
console.log(value);
// foo.js
module.exports = { value: 'foo' };Bundled output:
// #region rolldown:runtime
// ...runtime code
// #endregion
// #region foo.js
var require_foo = __commonJS({
'foo.js'(exports, module) {
module.exports = { value: 'foo' };
},
});
// #endregion
// #region index.js
var import_foo = __toESM(require_foo());
console.log(import_foo.value);
// #endregionThe __toESM helper ensures that CommonJS exports are properly converted to ES module format, allowing seamless access to the exported values.
require external modules
When platform: 'node' is set, Rolldown will generate a require function from module.createRequire.
For other platforms, Rolldown will leave it as it is, so ensure that the running environment provides a require function or inject one manually.
For example, you can inject the require function that returns the value obtained by import by using inject feature.
import path from 'node:path';
export default {
inject: {
require: path.resolve('./require.js'),
},
};import fs from 'node:fs';
export default (id) => {
if (id === 'node:fs') {
return fs;
}
throw new Error(`Requiring ${JSON.stringify(id)} is not allowed.`);
};You can also use the built-in esmExternalRequirePlugin to convert require() calls to import statements.
Future Plans
Rolldown's first-class support for CommonJS modules enables several potential optimizations:
- Advanced tree-shaking capabilities for CommonJS modules
- Better dead code elimination