10

I am working in NodeJS. I have a great deal of legacy code including several packages that are used in many places. This code is all CommonJS, Node require() module structures.

Node now supports ES6. Since it is a Javascript language feature, I would like to migrate to it.

Today, I started a small project. My small project boilerplate requires() a couple of my favorite utilities and then says 'Hello World'. I edited it to import said utilities. Node told me I needed to add "type":"module" to my package.json and I did.

When I ran it, I was told that "require is not defined", this in reference to one of the utility modules I imported.

I infer that this means that a project is either CommonJS or ES6 and it appears that never the twain shall meet. I am surprised by this because it means that I will never use ES6 in NodeJS because I will never be able to change all of the modules I require(). Some are not even mine, others are used in projects (npm!) that I do not even know about.

Honestly, I have a hard time believing that this is the case. I don't understand how ES6 can ever become a widely used standard because of if ES^ and CommonJS cannot be used together in an application. I realize that Webpack, etc, will preprocess code and revise all the require() statements but not everyone uses that sort of utility.

My questions are:

Is this analysis correct?

Is there some workaround that will let me use both module systems (without a preprocessor)?

Is my impending decision to never, ever use ES6 the right one?

tqwhite
  • 658
  • 7
  • 16
  • Different packages should be able to use different module formats. Have a look at https://stackoverflow.com/q/61549406/1048572 – Bergi Apr 24 '21 at 20:41
  • https://pencilflip.medium.com/using-es-modules-with-commonjs-modules-in-node-js-1015786dab03 – Avshalom N. Israel Aug 03 '21 at 07:48
  • I can't see anything that properly and clearly answers this question... did you work out a way of mixing and matching? – drmrbrewer Nov 04 '21 at 07:42
  • I did not find a decent way to mix module formats. In various places, people suggested cumbersome workarounds. I have been writing NodeJS code since 2010. I have a ton of useful library code in CommonJS. I have concluded that I will never use ES6. There is no possibility that ES6 modules provide sufficient benefit to rewrite everything. – tqwhite Oct 20 '22 at 11:27
  • I think mixing up both ways don't actually give you any benefits. If you are building a new application it is good to use ES-6 but if you are building an application win nodejs previous version then it is best to use commonjs format. – Ayemun Hossain Ashik Apr 27 '23 at 07:15

3 Answers3

2

I'm NOT a javascript person so I humbly accept any corrections here. I had the same question and was surprised at the lack of clarity on it in the usual places.

The confusing thing is that where you actually mix these, there are two files (modules) involved - the importing file and the imported file. So, if your index (or other entry point) file is ES-based and it needs to include a CommonJS file - which format do you use? For the most common basic case of importing CommonJS files/libraries into a modern ES6 app):

  1. Do NOT specify type:module in package.json (this leaves the default as CommonJS)
  2. File Extensions: Use the .mjs extension for all of the ES6 files. Use (or leave) the older .js extension for all of the CommonJS files
  3. Export statements: Use export keyword (e.g."export functionName") for all ES6 exports - use "module.exports" for all CommonJS exports
  4. Import statements: use the importing syntax for whatever file type you are importing to. For example, if you are in an ES6 module file and need to bring in a CommonJS file, use the ES6 import syntax

enter image description here

  • It should be `module.exports` and not `modules.export`. And yeah, unfortunately, anything JS-related always lacks explanations. – Darya Balu Dec 16 '22 at 11:32
  • Please [do not post paintings of code](https://meta.stackoverflow.com/q/285551/1048572)! – Bergi Dec 17 '22 at 20:45
2

For node.js 16.18.0

package.json

{
  "name": "es6_commonjs",
  "version": "1.0.0",
  "description": "",
  "type": "module",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

book.cjs

module.exports = class Book {
    constructor(name) {
        this.name = name;
    }
}

student.js

export class Student {
    constructor(name) {
        this.name = name;
    }
}

app.js

import { Student } from "./student.js";
import Book from './book.cjs';

const student = new Student('Name');
console.log(student);

const book = new Book('Name');
console.log(book);

run command node ./app.js

result:

Student { name: 'Name' }
Book { name: 'Name' }
rukonmin
  • 21
  • 2
-2

use import( ... ) in .cjs or .mjs files

see

rukonmin
  • 21
  • 2
  • 7
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/late-answers/30043377) – eglease Oct 11 '21 at 05:09
  • This post does not address the question of using ES6 alongside CommonJS modules. These are links to information about using the Import statement and not useful. – tqwhite Oct 20 '22 at 11:30