35

I have a node app that I'd like to use in the standard ES6 module format (i.e., "type": "module" in the package.json, and using import and export throughout) without transpiling down to ES5. But I would like to take advantage of some older libraries such as a express and socket.io that use CommonJS / require format. What are my options (as of 5/2020, Node 12.16.3) for combining CommonJS modules into an ES6 app?

1
  • 2
    You can mix and match the two? I don't think you'll have any issues. Commented May 3, 2020 at 20:17

4 Answers 4

43
+50

Working with CommonJS modules is pretty straight forward. You can only do default exports from CommonJS modules.

import packageMain from 'commonjs-package'; // Works
import { method } from 'commonjs-package'; // Errors

This means that all commonjs exports will live on the packageMain object, and you need to dot in to the packageMain object to pickup what you need.

packageMain.method1()

More info in the official nodejs docs

Sign up to request clarification or add additional context in comments.

1 Comment

Starting from nodejs v14.13.0 it is possible to use qualified imports of CJS modules.
16

Since Node 13.10, there is another option, the most forward-looking one:

File an issue in the repo of the CommonJS library you'd like to use, persuading the maintainers to publish dual packages (ESM + CommonJS), using conditional exports.

For libraries written in TypeScript, generating dual packages is easy, and doesn't require Babel or rollup or any additional tools. Here's how I did it in local-iso-dt:

Relevant parts of package.json:

{
  "name": "local-iso-dt",
  "version": "3.1.0",
  "description": "...",
  "type": "commonjs",
  "exports": {
    "node": {
      "import": "./index.mjs",
      "require": "./index.js"
    },
    "default": "./index.mjs"
  },
  "main": "index.js",
  "files": [
    "index.ts",
    "index.mjs",
    "index.js"
  ],
  "scripts": {
    "clean": "rm index*.js index.mjs",
    "prepublishOnly:cjs": "tsc index.ts --esModuleInterop --removeComments",
    "prepublishOnly:esm": "tsc index.ts -t ES2015 --types node && mv index.js index.mjs",
    "prepublishOnly": "npm run prepublishOnly:esm; npm run prepublishOnly:cjs"
  },
  "devDependencies": {
    "typescript": "^4.0.2"
  },
}

prepublishOnly:esm renames the output manually because TypeScript can't yet generate .mjs output directly and --outFile doesn't work with ES Modules.

The exports block has the "conditional exports that enable TypeScript code transpiled with ES Modules, to use named imports. TypeScript doesn't directly support .mjs input files.

No tsconfig.json was necessary for this simple module.

Comments

4

Ivan's answer is helpful, but I also should note that that because I was using node 12.16.3, I also needed to add the --experimental-modules flag to my start script in package.json:

"type": "module",
"scripts": {
    "start": "node --experimental-modules --experimental-json-modules server.mjs",
}
  • "type": "module" tells node that you should use ES6 modules
  • file name of .mjs further makes it clear that we're working with a module JavaScript file
  • --experimental-modules and --experimental-json-modules let you use import in node version 12.

Then I was able to do things like import express from 'express'; (where express 4.17.1 is a CommonJS module), and it worked fine.

1 Comment

Almost everything tried after 8 hours of struggling... Thank you my savior
1

Make sure the module in question has an index.js that exports the code you want to import or require.

In package.json, under the dependencies attribute, add:

"myCustomModule":"file:./path/to/myCustomModule"

After you have done this run npm install.

Once that is completed look inside the project's node_modules/ and you will see a directory named myCustomModule.

Now in any project file you can import or require that code as you would any other mode_module

1 Comment

How does an index.js export code you want to import? The module in question is a commonjs module.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.