package.json 中 main/module/browser/exports 字段有何区别
Issue 欢迎在 Gtihub Issue 中回答此问题: Issue 535 (opens in a new tab)
Author 回答者: shfshanyue (opens in a new tab)
main
main
指 npm package 的入口文件,当我们对某个 package 进行导入时,实际上导入的是 main
字段所指向的文件。
main
是 CommonJS 时代的产物,也是最古老且最常用的入口文件。
// package.json 内容
{
name: 'midash',
main: './dist/index.js'
}
// 关于如何引用 package
const midash = require('midash')
// 实际上是通过 main 字段来找到入口文件,等同于该引用
const midash = require('midash/dist/index.js')
module
随着 ESM 且打包工具的发展,许多 package 会打包 N 份模块化格式进行分发,如 antd
既支持 ES
,也支持 umd
,将会打包两份。
如果使用 import
对该库进行导入,则首次寻找 module
字段引入,否则引入 main
字段。
基于此,许多前端友好的库,都进行了以下分发操作:
- 对代码进行两份格式打包:
commonjs
与es module
module
字段作为es module
入口main
字段作为commonjs
入口
{
name: 'midash',
main: './dist/index.js',
module: './dist/index.mjs'
}
// 以下两者等同
import midash from 'midash'
import midash from 'midash/dist/index.mjs'
如果你的代码只分发一份 es module
模块化方案,则直接置于 main
字段之中。
exports
如果说以上两个是刀剑,那 exports
至少得是瑞士军刀。
exports
可以更容易地控制子目录的访问路径,也被称为 export map
。
假设我们 Package 的目录如下所示:
├── package.json
├── index.js
└── src
└── get.js
不在 exports
字段中的模块,即使直接访问路径,也无法引用!
// package.json
{
name: 'midash',
main: './index.js',
exports: {
'.': './dist/index.js',
'get': './dist/get.js'
}
}
// 正常工作
import get from 'midash/get'
// 无法正常工作,无法引入
import get from 'midash/dist/get'
exports
不仅可根据模块化方案不同选择不同的入口文件,还可以根据环境变量(NODE_ENV
)、运行环境(nodejs
/browser
/electron
) 导入不同的入口文件。
{
"type": "module",
"exports": {
"electron": {
"node": {
"development": {
"module": "./index-electron-node-with-devtools.js",
"import": "./wrapper-electron-node-with-devtools.js",
"require": "./index-electron-node-with-devtools.cjs"
},
"production": {
"module": "./index-electron-node-optimized.js",
"import": "./wrapper-electron-node-optimized.js",
"require": "./index-electron-node-optimized.cjs"
},
"default": "./wrapper-electron-node-process-env.cjs"
},
"development": "./index-electron-with-devtools.js",
"production": "./index-electron-optimized.js",
"default": "./index-electron-optimized.js"
},
"node": {
"development": {
"module": "./index-node-with-devtools.js",
"import": "./wrapper-node-with-devtools.js",
"require": "./index-node-with-devtools.cjs"
},
"production": {
"module": "./index-node-optimized.js",
"import": "./wrapper-node-optimized.js",
"require": "./index-node-optimized.cjs"
},
"default": "./wrapper-node-process-env.cjs"
},
"development": "./index-with-devtools.js",
"production": "./index-optimized.js",
"default": "./index-optimized.js"
}
}
Author 回答者: GiveMe-A-Name (opens in a new tab)
想知道 main/module/browser/exports
直接的优先级,在 package.json
中同时指定这些,会优先以 exports
为准吗?