browser
VS module
VS main
前端开发中使用到 npm
包那可算是屡见不鲜,而使用到 npm
包总免不了接触到 package.json
包配置文件。javascript
那么这里就有一个问题,当咱们在不一样环境下 import
一个 npm
包时,到底加载的是 npm
包的哪一个文件?前端
老司机们很快地给出答案:main
字段中指定的文件。java
然而咱们清楚 npm
包其实又分为:node
若是咱们须要开发一个 npm
包同时兼容支持 web端 和 server 端,须要在不一样环境下加载npm包不一样的入口文件,显然一个 main
字段已经不可以知足咱们的需求,这就衍生出来了 module
与 browser
字段。webpack
本文就来讲下 这几个字段的使用场景,以及同时存在这几个字段时,他们之间的优先级。git
在说 package.json
以前,先说下文件优先级github
因为咱们使用的模块规范有 ESM 和 commonJS 两种,为了能在 node 环境下原生执行 ESM 规范的脚本文件,.mjs
文件就应运而生。web
当存在 index.mjs
和 index.js
这种同名不一样后缀的文件时,import './index'
或者 require('./index')
是会优先加载 index.mjs
文件的。面试
也就是说,优先级 mjs
> js
npm
browser
,module
和 main
字段main
: 定义了 npm
包的入口文件,browser 环境和 node 环境都可使用module
: 定义 npm
包的 ESM 规范的入口文件,browser 环境和 node 环境都可使用browser
: 定义 npm
包在 browser 环境下的入口文件首先,咱们假定 npm
包 test
有如下目录结构
----- lib
|-- index.browser.js
|-- index.browser.mjs
|-- index.js
|-- index.mjs
复制代码
其中 *.js
文件是使用 commonJS 规范的语法(require('xxx')
),*.mjs
是用 ESM 规范的语法(import 'xxx'
)
其 package.json 文件:
"main": "lib/index.js", // main
"module": "lib/index.mjs", // module
// browser 可定义成和 main/module 字段一一对应的映射对象,也能够直接定义为字符串
"browser": {
"./lib/index.js": "./lib/index.browser.js", // browser+cjs
"./lib/index.mjs": "./lib/index.browser.mjs" // browser+mjs
},
// "browser": "./lib/index.browser.js" // browser
复制代码
根据上述配置,那么其实咱们的 package.json
指定的入口能够有
main
module
browser
browser+cjs
browser+mjs
这 5 种状况。下面说下具体使用场景。
这是咱们最多见的使用场景,经过 webpack
打包构建咱们的 web 应用,模块语法使用 ESM
当咱们加载
import test from 'test'
复制代码
实际上的加载优先级是 browser
= browser+mjs
> module
> browser+cjs
> main
也就是说 webpack 会根据这个顺序去寻找字段指定的文件,直到找到为止。
然而实际上的状况可能比这个更加复杂,具体能够参考流程图
const test = require('test')
复制代码
事实上,构建 web 应用时,使用 ESM
或者 commonJS
模块规范对于加载优先级并无任何影响
优先级依然是 browser
= browser+mjs
> module
> browser+cjs
> main
咱们清楚,使用 webpack 构建项目的时候,有一个 target 选项,默认为 web,即进行 web 应用构建。
当咱们须要进行一些 同构项目,或者其余 node 项目的构建的时候,咱们须要将 webpack.config.js
的 target
选项设置为 node
进行构建。
import test from 'test'
// 或者 const test = require('test')
复制代码
优先级是: module > main
经过 node test.js
直接执行脚本
const test = require('test')
复制代码
只有 main 字段有效。
经过 --experimental-modules
可让 node 执行 ESM 规范的脚本(必须是 mjs 文件后缀)
`node --experimental-modules test.mjs
import test from 'test'
复制代码
只有 main 字段有效。
npm
包导出的是 ESM 规范的包,使用 modulenpm
包只在 web 端使用,而且严禁在 server 端使用,使用 browser。npm
包只在 server 端使用,使用 mainnpm
包在 web 端和 server 端都容许使用,使用 browser 和 mainnpm
包须要提供 commonJS 与 ESM 等多个规范的多个代码文件,请参考上述使用场景或流程图插播广告:
深圳 Shopee 长期内推
岗位:前端,后端(要转go),产品,UI,测试,安卓,IOS,运维 全都要。
薪酬福利:20K-50K😳,7点下班😏,免费水果😍,免费晚餐😊,15天年假👏,14天带薪病假。 点击查看详情 简历发邮箱:chenweiyu6909@gmail.com 或者加我微信:cwy13920,实时反馈面试进度哦。