在大家抽象业务,搭建公共组件时会涉及与Node的交互,在这是会发现一些奇奇怪怪的问题
- 为什么import … from …在Node中执行不成功,必须通过require的执行呢?
- 为什么通过Node执行创建的package时会不成功呢?
- 为什么别人的项目在引用时能引用出不同的文件呢?
Note 诸如此类的问题,其实都是通过package.json配置能解决的,这次咱们就一起看看package.json中的哪些字段会影响Node.js运行
package.json中与Node.js相关的字段
Node.js使用package.json中的字段列表
- "
name" - 被包管理器(package managers)用作对当前包的命名。可以被包通过name导入。 - "
main" - 加载包时的默认模块,如果exports没有定义,在Node.js制定的版本中指定导出内容 - "
packageManager" - 实验属性,当包被使用时推荐使用的包管理工具,被Node.js中的Corepack使用。 - "
type" - 决定将.js文件加载为CommonJS还是ESmodules。 - "
exports" - 定义包的exports的内容。如果存在,可以限制从包中加载的子模块。 - "
imports" - 包导入,供包自身的module使用。
"name"
- Type: <
string>
"name": "package-name"
name字段定义了你的包名,当publish的时候需要name字段符合npm对name的规范
name可以被加到exports字段中供自身调用
"main"
- NodeVersion:v0.4.0
- Type: <
string>
{
"main": "./main.js"
}
main字段是一个地址,定义package通过name被引入时的入口。当包有exports字段,包通过name被引用时,exports字段的优先级高于main字段。也是通过require加载package时的入口文件
require('./path/to/directory'); // This resolves to ./path/to/directory/main.js.
"packageManager"
- NodeVersion:v16.9.0, v14.19.0
- Type:<
string> - Note: 因为Node.js的
Corepack是实验属性,需要手动打开Corepack才有效
{
"packageManager": "<package manager name>@<version>"
}
packageManager字段定义当package运行在对应得项目中时哪个package manager(npm or yarn …)更好。可以设置为任何支持的package manager, 确保团队中使用相同的package manager版本不用安装Node.js之外的其他东西
这个字段是实验属性需要手动打开;
"type"
- Type:<
string>
type字段定义了module中Node.js在使用所有将package.json作为最近父级的.js文件的格式。当以包含"type"字段值为"module"的package.json为最近父级的所有.js文件都将被作为ES module加载。如果最近的package.json没有,就会持续向上层文件查找直到到达根目录。
{
"type": "modules"
}
如果最近的父级package.json缺少"type"字段或者值为"commonjs",则.js文件被视为CommonJS。如果到根目录也没有找到package.json, .js文件将被视为CommonJS。
import一个.js文件,如果这个文件的最近父级package.json包含"type": "module",那么这个文件将被当为ES modules使用。
import './startup.js'; // Loaded as ES module because of package.json
无论"type"字段的值是什么,.mjs文件始终被视为ES module,.cjs文件始终被视为CommonJS。
"exports"
- Type:<
Object> | <string> | <string[]>
"exports": {
"./package.json": "./package.json",
".": [
{
"import": "./index.mjs",
"require": "./index.cjs"
},
"./index.cjs"
],
"./helpers": {
"import": "./helpers/helpers.mjs",
"require": "./helpers/index.js"
},
"./browser": {
"import": "./browser.mjs",
"types": "./browser.d.ts"
}
},
exports字段可以定义在通过查找或对其自身名称的自引用加载的名称导入时定义包的入口点。在Node.js 12+的版本中支持作为"main"的替代品,定义子路径导出或者条件导出同时封装内部未导出的模块。
条件导出可以在exports为每个环境定义不同的package入口,甚至包括package是通过require还是import调用
所有在exports中定义的路径必须通过./开始链接文件路径
"imports"
- NodeVersion:v14.6.0, v12.19.0
- Type:<
Object>
{
"imports": {
"#dep": {
"node": "dep-node-native",
"default": "./dep-polyfill.js"
}
},
"dependencies": {
"dep-node-native": "^1.0.0"
}
}
imports字段中的key必须是以#开始的字符串
导入映射允许映射到package的外部
此字段定义当前package的导入的子路径