Older Node.js projects often keep CommonJS files beside code that already uses import and export. Converting one module pair at a time keeps the migration small, lets existing tests catch behavior changes, and makes the runtime boundary clear before more files depend on it.
A package-level conversion uses package.json with "type": "module" so converted .js files run as ES modules. Files that still need require() or module.exports should stay on the .cjs extension until they are converted.
ES modules require explicit relative file extensions, and CommonJS locals such as require, module.exports, filename, and dirname are not available as local bindings. Convert the import and export syntax deliberately, then run the project smoke or test script against the converted entry point.
$ node src/app.js total=107
{
"name": "module-convert-commonjs-esm",
"version": "1.0.0",
"type": "module",
"scripts": {
"smoke": "node src/app.js"
}
}
After "type": "module" is set, .js files in the package run as ES modules. Keep unconverted CommonJS files on .cjs or convert them before they are loaded.
export function totalWithTax(subtotal, taxRate) { return Number((subtotal * (1 + taxRate)).toFixed(2)); }
import { totalWithTax } from "./price.js"; console.log(`total=${totalWithTax(100, 0.07)}`);
Relative ES module imports in Node.js need the target file extension, such as ./price.js.
$ npm --silent run smoke total=107