当前位置:网站首页>Es module and commonjs learning notes -- ESM and CJS used in nodejs
Es module and commonjs learning notes -- ESM and CJS used in nodejs
2022-07-05 05:07:00 【Fierce chicken】
stay NodeJS Use in ES6 modular
The current newer version NodeJS Support ESM and CJS , But the default is CJS Specification to analyze JS Code , Use it directly CJS There is no problem , While using ESM Something needs to be done
.mjs
file
stay NodeJS of use .mjs
The suffix filename indicates that the file is ES6 Modular file , Can be in .mjs
Direct use in documents ESM grammar ( Use import/export
Instructions ). In execution, including ES6 The script of the module , Because of the difference NodeJS The degree of support of the version is different , It needs to be executed in different ways
v16.4.0 Fully support
v13.2.0 Experimental support , Omission --experimental-modules
Older versions require explicit use of parameters --experimental-modules perform or This experimental feature is not even supported
node --experimental-modules <path/to/file>
Modify the module specification
Can pass modify NodeJS analysis JS Code time module specification , bring ESM Can be directly in .js
Use... In the document ( If you don't modify it, you will report an error if you use it directly ). Create a package.json
file ( You can execute in the directory to be created npm init -y
Generate package.json
), And will "type"
Set to "module"
// ./package.json
{
"type": "module"
}
// When not set type Or set to "commonjs" It uses CJS standard
After the above configuration , If you want to use CJS grammar ( Use module.exports/require()
), You need to in .cjs
Use... In the document , Otherwise, an undefined error will be reported
When considered ES6 When the module , Will automatically adopt strict mode ( Browser side is the same )
ES6 modular and CommonJS Mutual reference of modules
ESM It is loaded at compile time ( Static loading ), There is a separate parsing phase for module dependencies , The output of the module is the interface ( quote ), Its loading 、 analysis 、 The execution is asynchronous ;CJS Is runtime load ( Dynamic loading ), The module outputs a value ( Module object ), Values are cached , Its loading 、 analysis 、 The execution is synchronous (require()
For a synchronous method ).
It can be seen from the above description of the two specifications , ESM and CJS The implementation of specifications is different , If you want to ES6 Introduced in the module CJS Module or in CJS Introduced in the module ES6 modular , You need to follow the following rules
CJS Module loading ES6 modular :
because ES6 For asynchronous loading ,CJS Load for synchronization , Can't be used directly require()
To load the ES6 modular , Can only Using the same asynchronous loading and CJS and ESM All supported import()
To load the
// import() Return to one promise
import('....').then(res => {
});
(async () => {
await import('....');
}())
ES6 Module loading CJS modular :
ESM Of import
Can be loaded directly CJS modular , But it can only be loaded as a whole . because ES6 Modules need to support static code analysis , and CommonJS The output interface of the module is module.exports
, It's an object , Cannot be statically analyzed , So it can only be loaded as a whole
import {
a } from "./foo.cjs"; // Report errors
import m from "./foo.cjs";
const {
a } = m; // The right way
require()
Can't be in .mjs
Use... In the document ( Only use import
or import()
), Nor can it be used to load .mjs
file ( That is, the above cannot be loaded ES6 modular )
Another thing to note , In the use of webpack In packaged projects , In the same file Don't suggest ESM and CJS A mixture of ,babel Translation can make ESM Turn into CJS, This may often lead to some inexplicable mistakes
// This is not recommended ,
import m from "./foo.js";
module.exports = {
m
}
https://github.com/xiaoxiaojx/blog/issues/27
https://www.tangshuang.net/7686.html
modular ( package ) Load the rules
By default ( Not through package.json
Of exports
Option to set the alias ),import
command Load one that is not node_modules
When the module under , Unless it is a system module , Otherwise, the suffix cannot be omitted , The complete file path must be given
// ./module/index.js
import "./foo/index.js";
// Even if ./foo/package.json Set the entrance "main": "index.js" Also can not import Directly introducing
import "./foo";
But for the CJS There are no such restrictions
// Can directly require introduce
require("./foo")
NodeJS Fully supported CJS standard , By default , Its loading rules are as follows
require("./foo/index.js");
// The detailed file path is provided ( Including file suffix ), If you can't find it, report an error directly
require("./foo");
/* Omitted file path or suffix ( It could be ./foo/index.js or ./foo.js), Look for : Find the same name JS file foo.js; Find a directory with the same name foo Under the index.js file ( If foo Under the package.json It specifies Entrance file , According to package.json Configuration search in ); No error found */
require("foo");
/* Provide only one string , Search according to the following rules : Find the system module with the same name ; lookup node_modules The files under the , First find the same name JS file foo.js, Then find the directory with the same name foo Next Of index.js file ( If foo Under the package.json Specifies the entry file , According to package.json Configuration search in ); No error found */
Configure the entry file and path alias
Can pass package.json
Medium main
and exports
Configure some settings to facilitate the introduction of modules
package.json
Mediummain
:
This is the designated module entry/* Suppose the directory structure is as follows ---foo |---index.js |---index2.js |---package.json */ // Suppose no configuration is done now , Then the default entry is index.js require("./foo"); // amount to ./foo/index.js // Suppose that package.json Add "main": "index2.js", Then the entrance becomes index2.js require("./foo"); // amount to ./foo/index2.js
package.json
Mediumexports
:exports
Has a higher priority thanmain
It can be used to set file path alias :
{ "exports": { "./foo": "./utils/foo", } }
As mentioned above ,
import
The module path introduced by the instruction must be complete , Here, you can simplify the path by configuring the path alias{ "exports": { "./foo": "./foo.js", } }
At this point, you can directly
import "./foo"
It can be used to set the main entrance main Path alias of :
use.
Indicates the main entrance{ "exports": { ".": "./index.js", } } // If only the main entry configuration can be slightly written as { "exports": "./index.js" }
because exports Fields only support ES6 Of Node.js Only then did I know , So it can be used to be compatible with old versions Node.js
// Take advantage of exports Priority is greater than main Characteristics { "main": "./index.js", "exports": "./index2.js" }
You can realize conditional loading :
Alias setting of the entry file.
in , There are also two sub configurationsrequire
anddefault
, Assign separately CJS And other entrances ( Include ESM){ "exports": { ".": { "require": "./index.cjs", // cjs entrance "default": "./index.mjs" // esm entrance } } } // Same , Here, if only the main entry is configured, the abbreviation can be used { "exports": { "require": "./index.cjs", // cjs entrance "default": "./index.mjs" // esm entrance } }
This function needs to be in Node.js When it's running , open
--experimental-conditional-exports
signnode --experimental-conditional-exports ....
Two formats of modules are supported at the same time
Specify different entry files
Through the above mentionedexports
Configuration to realize{ "exports": { ".": { "require": "./index.cjs", // cjs entrance "default": "./index.mjs" // esm entrance } } }
CJS and ESM Reciprocal transformation
CJS turn ESM:// from CJS Import module from module import m from "./foo.cjs"; // Extract what you need export const bar = m.bar; // ....
ESM turn CJS
// from ES6 Import module from module let m = null; (async () => { m = await import("./foo.mjs"); })() module.exports = { ...m }
Or use in subdirectories package.json
Of "type"
Configure the specifications used by the current module , Let a directory be CJS Format , Another directory is ESM Format , But after all, it still involves format conversion , The entry file specifies these configurations , For details, please refer to some existing packages , They often support both formats
ES6 Module considerations
import The limits of command
In addition to the aboveimport
when The path must be complete ( Include suffix ),import
The path of must also be a relative path , Cannot be an absolute path ( The browser can be an absolute path )、 Only local modules can be loadedFor and browser import The loading rules are the same ,NodeJS Of
.mjs
File support URL routeimport "./foo.mjs?query=10086"
As long as the parameters of the same script are different , Will be loaded many times , And saved into different caches ( When there are no parameters or the parameters are the same, it is loaded many times and executed only once ). For this reason , As long as the file name contains
:
、%
、#
、?
Equal special character , It is best to escape these charactersInternal variables
In order to make ES6 The module can be used in both server and browser without any modification ,NodeJS It is stipulated in ES6 Cannot be used in modules NodeJS Some internal variables ofarguments module exports require __dirname __filename
Reference resources :
https://es6.ruanyifeng.com/#docs/module-loader
https://es6.ruanyifeng.com/#docs/module
https://zhuanlan.zhihu.com/p/337796076
https://www.jianshu.com/p/1e42fcabf039
边栏推荐
猜你喜欢
UE 虚幻引擎,项目结构
Autocad-- dynamic zoom
Research on the value of background repeat of background tiling
AutoCAD - command repetition, undo and redo
AutoCAD - window zoom
Unity ugui source code graphic
AutoCAD - Center zoom
Generate filled text and pictures
3dsmax scanning function point connection drawing connection line
Learning notes of "hands on learning in depth"
随机推荐
Panel panel of UI
An article takes you to thoroughly understand descriptors
LeetCode之单词搜索(回溯法求解)
cocos_ Lua loads the file generated by bmfont fnt
Flink cluster configuration
2022/7/1學習總結
中国AS树脂市场调研与投资预测报告(2022版)
A three-dimensional button
AutoCAD - set layer
Animation
cocos_ Lua listview loads too much data
PR first time
2022/7/2做题总结
AutoCAD - workspace settings
【论文笔记】Multi-Goal Reinforcement Learning: Challenging Robotics Environments and Request for Research
嵌入式数据库开发编程(零)
MySQL audit log archiving
【Leetcode】1352. Product of the last K numbers
C iterator
Use of snippets in vscode (code template)