Security News
JSR Working Group Kicks Off with Ambitious Roadmap and Plans for Open Governance
At its inaugural meeting, the JSR Working Group outlined plans for an open governance model and a roadmap to enhance JavaScript package management.
@rollup/plugin-commonjs
Advanced tools
The @rollup/plugin-commonjs npm package is used to convert CommonJS modules to ES6, so they can be included in a Rollup bundle. This is necessary because Rollup, by default, only handles ES modules. The plugin provides a way to work with Node.js modules that use the CommonJS module system, which is not natively supported by Rollup.
Converting CommonJS to ES6 modules
This feature allows you to convert CommonJS modules into ES6 modules that Rollup can process. The code sample shows how to include the plugin in a Rollup configuration.
import commonjs from '@rollup/plugin-commonjs';
export default {
input: 'src/index.js',
output: {
file: 'bundle.js',
format: 'iife'
},
plugins: [
commonjs()
]
};
Handling mixed ES6 and CommonJS modules
This feature is useful when you have a project that contains a mix of ES6 and CommonJS modules. The plugin helps to resolve and convert these modules so they can be bundled together by Rollup. The code sample demonstrates how to use the commonjs plugin along with the node-resolve plugin to handle module resolution.
import commonjs from '@rollup/plugin-commonjs';
import resolve from '@rollup/plugin-node-resolve';
export default {
input: 'src/index.js',
output: {
file: 'bundle.js',
format: 'cjs'
},
plugins: [
resolve(),
commonjs()
]
};
Browserify is a tool for bundling up JavaScript files for usage in the browser. It also transforms Node.js-style CommonJS modules for browser usage, similar to what @rollup/plugin-commonjs does for Rollup. However, Browserify is a standalone bundling tool, whereas @rollup/plugin-commonjs is a plugin for Rollup.
Webpack is a powerful module bundler that can handle various module formats including CommonJS, AMD, and ES6 modules. It has built-in support for transforming CommonJS modules, similar to @rollup/plugin-commonjs, but it is more complex and configurable, offering a wide range of plugins and loaders for different tasks beyond module transformation.
Parcel is a web application bundler that supports many module types out of the box, including CommonJS. It offers a zero-configuration experience and handles module conversion internally, similar to what @rollup/plugin-commonjs does for Rollup. Parcel is known for its simplicity and speed compared to more configuration-heavy tools like Webpack.
🍣 A Rollup plugin to convert CommonJS modules to ES6, so they can be included in a Rollup bundle
This plugin requires an LTS Node version (v8.0.0+) and Rollup v1.20.0+.
Using npm:
npm install @rollup/plugin-commonjs --save-dev
Create a rollup.config.js
configuration file and import the plugin:
import commonjs from '@rollup/plugin-commonjs';
export default {
input: 'src/index.js',
output: {
dir: 'output',
format: 'cjs'
},
plugins: [commonjs()]
};
Then call rollup
either via the CLI or the API.
dynamicRequireTargets
Type: string | string[]
Default: []
Some modules contain dynamic require
calls, or require modules that contain circular dependencies, which are not handled well by static imports.
Including those modules as dynamicRequireTargets
will simulate a CommonJS (NodeJS-like) environment for them with support for dynamic and circular dependencies.
Note: In extreme cases, this feature may result in some paths being rendered as absolute in the final bundle. The plugin tries to avoid exposing paths from the local machine, but if you are dynamicRequirePaths
with paths that are far away from your project's folder, that may require replacing strings like "/Users/John/Desktop/foo-project/"
-> "/"
.
Example:
commonjs({
dynamicRequireTargets: [
// include using a glob pattern (either a string or an array of strings)
'node_modules/logform/*.js',
// exclude files that are known to not be required dynamically, this allows for better optimizations
'!node_modules/logform/index.js',
'!node_modules/logform/format.js',
'!node_modules/logform/levels.js',
'!node_modules/logform/browser.js'
]
});
exclude
Type: string | string[]
Default: null
A minimatch pattern, or array of patterns, which specifies the files in the build the plugin should ignore. By default, all files with extensions other than those in extensions
or ".cjs"
are ignored, but you can exclude additional files. See also the include
option.
include
Type: string | string[]
Default: null
A minimatch pattern, or array of patterns, which specifies the files in the build the plugin should operate on. By default, all files with extension ".cjs"
or those in extensions
are included, but you can narrow this list by only including specific files. These files will be analyzed and transpiled if either the analysis does not find ES module specific statements or transformMixedEsModules
is true
.
extensions
Type: string[]
Default: ['.js']
For extensionless imports, search for extensions other than .js in the order specified. Note that you need to make sure that non-JavaScript files are transpiled by another plugin first.
ignoreGlobal
Type: boolean
Default: false
If true, uses of global
won't be dealt with by this plugin.
sourceMap
Type: boolean
Default: true
If false, skips source map generation for CommonJS modules. This will improve performance.
transformMixedEsModules
Type: boolean
Default: false
Instructs the plugin whether to enable mixed module transformations. This is useful in scenarios with modules that contain a mix of ES import
statements and CommonJS require
expressions. Set to true
if require
calls should be transformed to imports in mixed modules, or false
if the require
expressions should survive the transformation. The latter can be important if the code contains environment detection, or you are coding for an environment with special treatment for require
calls such as ElectronJS. See also the "ignore" option.
ignore
Type: string[] | ((id: string) => boolean)
Default: []
Sometimes you have to leave require statements unconverted. Pass an array containing the IDs or an id => boolean
function.
ignoreTryCatch
Type: boolean | 'remove' | string[] | ((id: string) => boolean)
Default: false
In most cases, where require
calls are inside a try-catch
clause, they should be left unconverted as it requires an optional dependency that may or may not be installed beside the rolled up package.
Due to the conversion of require
to a static import
- the call is hoisted to the top of the file, outside of the try-catch
clause.
true
: All require
calls inside a try
will be left unconverted.false
: All require
calls inside a try
will be converted as if the try-catch
clause is not there.remove
: Remove all require
calls from inside any try
block.string[]
: Pass an array containing the IDs to left unconverted.((id: string) => boolean|'remove')
: Pass a function that control individual IDs.esmExternals
Type: boolean | string[] | ((id: string) => boolean)
Default: false
Controls how to render imports from external dependencies. By default, this plugin assumes that all external dependencies are CommonJS. This means they are rendered as default imports to be compatible with e.g. NodeJS where ES modules can only import a default export from a CommonJS dependency:
// input
const foo = require('foo');
// output
import foo from 'foo';
This is likely not desired for ES module dependencies: Here require
should usually return the namespace to be compatible with how bundled modules are handled.
If you set esmExternals
to true
, this plugins assumes that all external dependencies are ES modules and will adhere to the requireReturnsDefault
option. If that option is not set, they will be rendered as namespace imports.
You can also supply an array of ids to be treated as ES modules, or a function that will be passed each external id to determine if it is an ES module.
requireReturnsDefault
Type: boolean | "namespace" | "auto" | "preferred" | ((id: string) => boolean | "auto" | "preferred")
Default: false
Controls what is returned when requiring an ES module from a CommonJS file. When using the esmExternals
option, this will also apply to external modules. By default, this plugin will render those imports as namespace imports, i.e.
// input
const foo = require('foo');
// output
import * as foo from 'foo';
This is in line with how other bundlers handle this situation and is also the most likely behaviour in case Node should ever support this. However there are some situations where this may not be desired:
There is code in an external dependency that cannot be changed where a require
statement expects the default export to be returned from an ES module.
If the imported module is in the same bundle, Rollup will generate a namespace object for the imported module which can increase bundle size unnecessarily:
// input: main.js
const dep = require('./dep.js');
console.log(dep.default);
// input: dep.js
export default 'foo';
// output
var dep = 'foo';
var dep$1 = /*#__PURE__*/ Object.freeze({
__proto__: null,
default: dep
});
console.log(dep$1.default);
For these situations, you can change Rollup's behaviour either globally or per module. To change it globally, set the requireReturnsDefault
option to one of the following values:
false
: This is the default, requiring an ES module returns its namespace. This is the only option that will also add a marker __esModule: true
to the namespace to support interop patterns in CommonJS modules that are transpiled ES modules.
// input
const dep = require('dep');
console.log(dep);
// output
import * as dep$1 from 'dep';
function getAugmentedNamespace(n) {
var a = Object.defineProperty({}, '__esModule', { value: true });
Object.keys(n).forEach(function (k) {
var d = Object.getOwnPropertyDescriptor(n, k);
Object.defineProperty(
a,
k,
d.get
? d
: {
enumerable: true,
get: function () {
return n[k];
}
}
);
});
return a;
}
var dep = /*@__PURE__*/ getAugmentedNamespace(dep$1);
console.log(dep);
"namespace"
: Like false
, requiring an ES module returns its namespace, but the plugin does not add the __esModule
marker and thus creates more efficient code. For external dependencies when using esmExternals: true
, no additional interop code is generated.
// output
import * as dep from 'dep';
console.log(dep);
"auto"
: This is complementary to how output.exports
: "auto"
works in Rollup: If a module has a default export and no named exports, requiring that module returns the default export. In all other cases, the namespace is returned. For external dependencies when using esmExternals: true
, a corresponding interop helper is added:
// output
import * as dep$1 from 'dep';
function getDefaultExportFromNamespaceIfNotNamed(n) {
return n && Object.prototype.hasOwnProperty.call(n, 'default') && Object.keys(n).length === 1 ? n['default'] : n;
}
var dep = getDefaultExportFromNamespaceIfNotNamed(dep$1);
console.log(dep);
"preferred"
: If a module has a default export, requiring that module always returns the default export, no matter whether additional named exports exist. This is similar to how previous versions of this plugin worked. Again for external dependencies when using esmExternals: true
, an interop helper is added:
// output
import * as dep$1 from 'dep';
function getDefaultExportFromNamespaceIfPresent(n) {
return n && Object.prototype.hasOwnProperty.call(n, 'default') ? n['default'] : n;
}
var dep = getDefaultExportFromNamespaceIfPresent(dep$1);
console.log(dep);
true
: This will always try to return the default export on require without checking if it actually exists. This can throw at build time if there is no default export. This is how external dependencies are handled when esmExternals
is not used. The advantage over the other options is that, like false
, this does not add an interop helper for external dependencies, keeping the code lean:
// output
import dep from 'dep';
console.log(dep);
To change this for individual modules, you can supply a function for requireReturnsDefault
instead. This function will then be called once for each required ES module or external dependency with the corresponding id and allows you to return different values for different modules.
Since most CommonJS packages you are importing are probably dependencies in node_modules
, you may need to use @rollup/plugin-node-resolve:
// rollup.config.js
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
export default {
input: 'main.js',
output: {
file: 'bundle.js',
format: 'iife',
name: 'MyModule'
},
plugins: [resolve(), commonjs()]
};
Symlinks are common in monorepos and are also created by the npm link
command. Rollup with @rollup/plugin-node-resolve
resolves modules to their real paths by default. So include
and exclude
paths should handle real paths rather than symlinked paths (e.g. ../common/node_modules/**
instead of node_modules/**
). You may also use a regular expression for include
that works regardless of base path. Try this:
commonjs({
include: /node_modules/
});
Whether symlinked module paths are realpathed or preserved depends on Rollup's preserveSymlinks
setting, which is false by default, matching Node.js' default behavior. Setting preserveSymlinks
to true in your Rollup config will cause import
and export
to match based on symlinked paths instead.
ES modules are always parsed in strict mode. That means that certain non-strict constructs (like octal literals) will be treated as syntax errors when Rollup parses modules that use them. Some older CommonJS modules depend on those constructs, and if you depend on them your bundle will blow up. There's basically nothing we can do about that.
Luckily, there is absolutely no good reason not to use strict mode for everything — so the solution to this problem is to lobby the authors of those modules to update them.
This plugin exposes the result of its CommonJS file type detection for other plugins to use. You can access it via this.getModuleInfo
or the moduleParsed
hook:
function cjsDetectionPlugin() {
return {
name: 'cjs-detection',
moduleParsed({
id,
meta: {
commonjs: { isCommonJS }
}
}) {
console.log(`File ${id} is CommonJS: ${isCommonJS}`);
}
};
}
FAQs
Convert CommonJS modules to ES2015
The npm package @rollup/plugin-commonjs receives a total of 2,828,147 weekly downloads. As such, @rollup/plugin-commonjs popularity was classified as popular.
We found that @rollup/plugin-commonjs demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 4 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
At its inaugural meeting, the JSR Working Group outlined plans for an open governance model and a roadmap to enhance JavaScript package management.
Security News
Research
An advanced npm supply chain attack is leveraging Ethereum smart contracts for decentralized, persistent malware control, evading traditional defenses.
Security News
Research
Attackers are impersonating Sindre Sorhus on npm with a fake 'chalk-node' package containing a malicious backdoor to compromise developers' projects.