cjs-module-lexer
raw JSON → 2.2.0 verified Fri May 01 auth: no javascript
A fast CommonJS module syntax lexer that detects named exports and reexports from CJS modules, used in Node.js core for ESM interop. Current stable version: 2.2.0. Maintained by Node.js team; release cadence is irregular but active for parser bugs and performance improvements. Key differentiators: extremely fast (~90ms/MB cold, ~15ms/MB warm), frozen detection patterns to ensure backwards compatibility across Node.js versions, and support for transpiler variations (e.g., TypeScript, Babel). Provides both Node.js (CJS) and Wasm (ESM) builds, with TypeScript declarations included.
Common errors
error Error: Must call init() before parse() ↓
cause Using ESM import with Wasm build but not calling await init() first.
fix
Add await init(); before any parse() call in ESM context.
error TypeError: parse is not a function ↓
cause Importing cjs-module-lexer incorrectly in CJS, e.g., using default import or wrong destructure.
fix
Use const { parse } = require('cjs-module-lexer'); in CommonJS.
error ReferenceError: exports is not defined ↓
cause Trying to access exports in a context where the CJS wrapper (function(exports, module, require) { ... }) is not provided.
fix
Ensure source code is wrapped in a CommonJS module wrapper when lexing; the lexer expects valid CJS syntax.
error Warning: cjs-module-lexer detected a reexport but the path './foo' is not quoted? ↓
cause Using module.exports = require('./foo') without quotes around the path? Actually, the lexer expects string literals.
fix
Use require('./foo') with a string literal; ensure no dynamic expressions.
Warnings
breaking In v2.0.0, the Wasm build was introduced and the ESM API changed: init() must be called before parse(). Previously, init() was not required and Wasm was not used. ↓
fix Add await init() before calling parse() in ESM environments. CJS users are unaffected.
deprecated The detection patterns are frozen; new export patterns will not be added. This ensures backwards compatibility but means some modern CJS patterns may not be detected. ↓
fix Do not rely on detection of non-standard patterns. Ensure your code uses the documented export forms (e.g., exports.X = ..., module.exports = { ... }, Object.defineProperty(exports, ...)).
gotcha The lexer does not handle all JavaScript edge cases (e.g., dynamic require, conditional exports inside functions). It uses a token grammar that may miss exports with unusual whitespace or comments. ↓
fix Test your modules with the lexer to ensure expected exports are detected. For complex cases, consider alternative tools.
gotcha The `__esModule` export is always included in the exports array if Object.defineProperty(module.exports, '__esModule', ...) is present. This may be unexpected for some users. ↓
fix Filter out '__esModule' from exports if not needed: exports.filter(e => e !== '__esModule')
breaking Version 1.4.2 included a change that moved to a common wasm-builder, but this was later refined. Users upgrading from 1.x should test exports detection thoroughly. ↓
fix Upgrade to 2.2.0 or later, and verify export detection.
Install
npm install cjs-module-lexer yarn add cjs-module-lexer pnpm add cjs-module-lexer Imports
- parse wrong
const parse = require('cjs-module-lexer').parsecorrectimport { parse, init } from 'cjs-module-lexer' - init wrong
const { init } = require('cjs-module-lexer')correctimport { init } from 'cjs-module-lexer' - parse wrong
const cjsModuleLexer = require('cjs-module-lexer'); cjsModuleLexer.parse(source)correctconst { parse } = require('cjs-module-lexer'); parse(source)
Quickstart
import { parse, init } from 'cjs-module-lexer';
const source = `
module.exports.a = 'a';
if (maybe) module.exports = require('./dep1.js');
module.exports = { b, c: d };
`;
await init();
const { exports, reexports } = parse(source);
console.log(exports); // ['a', 'b', 'c', '__esModule']
console.log(reexports); // ['./dep1.js']