Node.js
中使用 package.json
文件中的以下字段:
name
- 在包中使用命名导入时相关。包管理器也将其用作包的名称。main
- 如果未指定导出,以及在引入导出之前的Node.js
版本中,加载包时的默认模块。packageManager
- 为包做贡献时推荐的包管理器。由Corepack
垫片利用。type
- 包类型决定是否将.js
文件加载为CommonJS
或ES
模块。exports
- 打包导出和有条件导出。如果存在,则限制可以从包内加载哪些子模块。imports
- 包导入,供包本身内的模块使用。
1.CommonJS
当作为初始输入传递给node时,或者被 import
语句或 import()
表达式引用时,Node.js
会将以下内容视为 CommonJS
:
Files with a .cjs extension
.
扩展名为 .cjs
文件。
Files with a .js extension when the nearest parent package.json file contains a top-level field "type" with a value of "commonjs"
. 当最近的父package.json
文件包含值为commonjs
的顶级字段type
时,具有.js
扩展名的文件。Strings passed in as an argument to --eval or --print, or piped to node via STDIN, with the flag --input-type=commonjs
. 字符串作为参数传入--eval
或--print
,或通过STDIN
通过管道传输到node
,并带有标志--input-type=commonjs
。
以 .cjs
结尾的文件始终作为 CommonJS
加载,无论最近的父 package.json
是什么。
2.ESM
当作为初始输入传递给 node
时,或者被 import
语句或 import()
表达式引用时,Node.js
会将以下内容视为 ES
模块:
Files with an .mjs extension
.
扩展名为 .mjs
文件。
Files with a .js extension when the nearest parent package.json file contains a top-level "type" field with a value of "module"
.
当最近的父 package.json
文件包含值为 module
的顶级 type
字段时,具有 .js
扩展名的文件。
Strings passed in as an argument to --eval, or piped to node via STDIN, with the flag --input-type=module
.
字符串作为参数传入 --eval
,或通过 STDIN
通过管道传输到 node
,并带有标志 --input-type=module
。
When using --experimental-detect-module, code containing syntax only successfully parsed as ES modules, such as import or export statements or import.meta, having no explicit marker of how it should be interpreted. Explicit markers are .mjs or .cjs extensions, package.json "type" fields with either "module" or "commonjs" values, or --input-type or --experimental-default-type flags. Dynamic import() expressions are supported in either CommonJS or ES modules and would not cause a file to be treated as an ES module
.
当使用 --experimental-detect-module
时,包含仅成功解析为 ES
模块的语法的代码,例如 import
或 export
语句或 import.meta
,没有明确标记应如何解释它。
显式标记是 .mjs
或 .cjs
扩展名、带有 module
或 commonjs
值的 package.json
type
字段,或者 --input-type
或--experimental-default-type
标志。 CommonJS
或 ES
模块都支持动态 import()
表达式,并且不会导致文件被视为 ES
模块。
以 .mjs
结尾的文件始终作为 ES
模块加载,无论最近的父 package.json
是什么。
import能够导入CommonJS模块 但require不能导入ES模块。
CommonJS模块中,可以使用import懒加载加载esm模块。
3.entry.cjs
package.json
中的 main
字段通常只能定义一个入口。
这样的话,往往只能使用 require('module')
,而是用 require('module/lib/module.js')
则会失败。
在这种场景下,可以在 package.json
中定义 exports
字段。
{
"exports": {
".": "./index.js",
"./lib/*": "./lib/*.js"
}
}
const message = require('commonjs-a')
console.log(message)
const libMessage = require('commonjs-a/lib')
console.log(libMessage)
4.entry.mjs
在包的 package.json
文件中,两个字段可以定义包的入口点: main
和 exports
。
这两个字段都适用于 ES
模块和 CommonJS
模块入口点。
所有版本的 Node.js
都支持 main
字段,但其功能有限:它仅定义包的主入口点。
exports
提供了 main
的现代替代方案,允许定义多个入口点、环境之间的条件入口解析支持,并防止除"exports"中定义的入口点之外的任何其他入口点。这种封装允许模块作者清楚地定义其包的公共接口。
对于针对当前支持的 Node.js
版本的新包,建议使用 exports
字段。对于支持 Node.js 10
及更低版本的包, main
字段是必需的。
如果同时定义了 exports
和 main
,则在受支持的 Node.js
版本中 exports
字段优先于 main
。
{
"name": "my-package",
"exports": {
".": "./lib/index.js",
"./lib": "./lib/index.js",
"./lib/index": "./lib/index.js",
"./lib/index.js": "./lib/index.js",
"./feature": "./feature/index.js",
"./feature/index": "./feature/index.js",
"./feature/index.js": "./feature/index.js",
"./package.json": "./package.json"
}
}
// const message = require('esm-a')
// console.log(message)
// const libMessage = require('esm-a/lib')
// console.log(libMessage)
import message from 'esm-a'
console.log(message)
import libMessage from 'esm-a/lib'
console.log(libMessage)