[Module] Mixed development of ES6 and cjs

[Module] Mixed development of ES6 and cjs

  • module language
  • Reasons for mixed development
  • Using ES6 in Nodejs
    • An explanation of dynamic loading
  • The module language of the project
  • CJS and ESM development
    • How to use modules
      • Common module introduction
      • Introduction of json file
      • Ordinary module export
    • CJS compatible with ESM
    • ESM compatible with CJS (recommended)
    • Global variables –dirname-filename-esm library
  • question
    • Error: EPERM: operation not permitted, rename
    • SyntaxError: Cannot use import statement outside a module
    • Error: Cannot find module ‘D:\serverjs\index’

Module language

Existing modular development languages mainly include:

  • CJS (CommonJS): Synchronous modular specification
  • ESM – is a module specification at the JavaScript language level. It aims to replace all other modular development specifications and become the standard module specification in the front-end field.

Because ESM is the next generation standard, try to use ESM when developing

Reasons for hybrid development

Because the CJS (CommonJS) specification was first used for development, and later with the beginning of the ES6 specification, most libraries were gradually converted to the ES6 specification, but some of them still used the CJS specification. In an ESM project, CJS was used modules, leading to mixed development of projects

Using ES6 in Nodejs

The difference between using ES6’s import / export and require in Node.js is mainly reflected in the following aspects:

  1. import / export is the modular syntax of ES6, and require is the modular syntax of Node.js
  2. import / export are static and can only be used at the top level of the module, while require is dynamic and can be used anywhere
  3. import / export can export multiple variables, functions, etc., while require can only export one object
  4. import / export is asynchronous loading of modules, while require is synchronous loading of modules

In general, if you are using ES6 syntax, it is recommended to use import / export, otherwise use require, but as mentioned above ESM It is the next generation standard, so it is gradually becoming more and more convenient for nodejs to use ES6.

Explanation on dynamic loading

address

Module language of the project

The type field in package.json is used to specify the type of project, and the default is commonjs. The values of type include:

  • commonjs: Indicates that the package is a CommonJS module (that is, the default module format of Node.js)
  • module: Indicates that the package is an ES module (that is, the standard ECMAScript module format)
  • json: Indicates that the package only contains JSON data, which can be imported through the require() function or the ES6 import statement.

In the project, the suffixes of different files indicate:
.cjs uses the CommonJS specification
.mjs uses ES specifications
.js is based on the type field in package.json.

Therefore, the mixed development of the project can be achieved through the above different file suffixes.

CJS and ESM development

There are many differences in the use of CJS and ESM specifications. The following are the various problems I encountered when upgrading a CJS project to the ESM specification.

How to use modules

CJS is introduced through require and exported through module.exports;

ESM is introduced through import and exported;

Ordinary module introduction

const path = require("path");//CJS
import path from "path";//ESJ

Introduction of json files

const pkg = require("../package"); //CJS gets package.json data

import pkg from "../package.json" assert {<!-- --> type: "json" };//ESJ

Import cannot directly introduce json files

Common module export

module.exports = upgrade;//cjs
export default upgrade;//esj

CJS is compatible with ESM

(async function() {<!-- -->
  const esm = await import('esm');
  esm.a();
  esm.b();
})();

ESM is compatible with CJS (recommended)

ESM can directly import the CJS module. More and more libraries use ESM. It is recommended that new projects give priority to using the ESM specification.

import {<!-- --> a, b } from 'cjs';
a();
b():
//or
import a from 'cjs';
a()

Global variable –dirname-filename-esm library

The __dirname and __filename global variables are not injected into ESM and can be obtained through the dirname-filename-esm library.

__dirname: The absolute path of the directory where the file to execute the command is located (excluding the current file name)
__filename: The absolute path of the current file (including the file name)

import {<!-- --> dirname } from 'dirname-filename-esm'

// Get the absolute path to the directory where the execution command file is located
const __dirname = dirname(import.meta)
console.log(__dirname)

import {<!-- --> filename } from 'dirname-filename-esm'
// Get the absolute path of the file
const __filename = filename(import.meta)

// If you do not introduce the library dirname-filename-esm, you can use the following method
// import { fileURLToPath } from 'node:url'
// const __filename = fileURLToPath(import.meta.url)

Question

Error: EPERM: operation not permitted, rename

Please check whether the current command is executed in the editor, whether the folder to be modified is open in the editor; if it is open, please close the editor and go to the corresponding project directory in the terminal such as cmd Execute under

Please check the command executed by the current command. Whether the folder or file with the name to be modified already exists, causing a naming conflict problem; if it already exists, modify the new name, or delete the existing one. naming

SyntaxError: Cannot use import statement outside a module

The problem is that the import import method is used in the cjs standard project. At this time:

  1. In the package.json file, type:commonjs indicates the use of CJS specifications
  2. The error file uses the js suffix and will follow the specifications set by package.json by default.
  3. The ESM specification is used in the error file.

The solution is to change the suffix of the error file to mjs, indicating that the current file uses the ESM specification

Error: Cannot find module D:\serverjs\index’

This problem is caused by running a certain command test defined in the script in the package:

{<!-- -->
  "script":{<!-- -->
    "test" :"node ./serverjs/index"
  }
}

Error reported after running:
`
node:internal/modules/cjs/loader:936
throw err;

Error: Cannot find module D:\serverjs\index’
`
Then find that the file does exist, but the suffix is “.mjs”, so the command cannot automatically identify non-js files with suffixes. You need to specify the suffix in the command.

node ./serverjs/lowdb/bin/index.mjs

problem solved!!!