[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:
import
/export
is the modular syntax of ES6, andrequire
is the modular syntax of Node.jsimport
/export
are static and can only be used at the top level of the module, whilerequire
is dynamic and can be used anywhereimport
/export
can export multiple variables, functions, etc., whilerequire
can only export one objectimport
/export
is asynchronous loading of modules, whilerequire
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:
- In the package.json file, type:commonjs indicates the use of CJS specifications
- The error file uses the js suffix and will follow the specifications set by package.json by default.
- 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!!!