摘要:本文就来说下这几个字段的使用场景,以及同时存在这几个字段时,他们之间的优先级。当存在和这种同名不同后缀的文件时,或者是会优先加载文件的。或者优先级是通过直接执行脚本只有字段有效。
browser VS module VS main
前端开发中使用到 npm 包那可算是家常便饭,而使用到 npm 包总免不了接触到 package.json 包配置文件。
那么这里就有一个问题,当我们在不同环境下 import 一个 npm 包时,到底加载的是 npm 包的哪个文件?
老司机们很快地给出答案:main 字段中指定的文件。
然而我们清楚 npm 包其实又分为:
只允许在客户端使用的,
只允许造服务端使用的,
浏览器/服务端都可以使用。
如果我们需要开发一个 npm 包同时兼容支持 web端 和 server 端,需要在不同环境下加载npm包不同的入口文件,显然一个 main 字段已经不能够满足我们的需求,这就衍生出来了 module 与 browser 字段。
本文就来说下 这几个字段的使用场景,以及同时存在这几个字段时,他们之间的优先级。
文件优先级在说 package.json 之前,先说下文件优先级
由于我们使用的模块规范有 ESM 和 commonJS 两种,为了能在 node 环境下原生执行 ESM 规范的脚本文件,.mjs 文件就应运而生。
当存在 index.mjs 和 index.js 这种同名不同后缀的文件时,import "./index" 或者 require("./index") 是会优先加载 index.mjs 文件的。
也就是说,优先级 mjs > js
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这是我们最常见的使用场景,通过 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 + node + ESM/commonJS我们清楚,使用 webpack 构建项目的时候,有一个 target 选项,默认为 web,即进行 web 应用构建。
当我们需要进行一些 同构项目,或者其他 node 项目的构建的时候,我们需要将 webpack.config.js 的 target 选项设置为 node 进行构建。
import test from "test" // 或者 const test = require("test")
优先级是: module > main
node + commonJS通过 node test.js 直接执行脚本
const test = require("test")
只有 main 字段有效。
node + ESM通过 --experimental-modules 可以让 node 执行 ESM 规范的脚本(必须是 mjs 文件后缀)
`node --experimental-modules test.mjs
import test from "test"
只有 main 字段有效。
总结如果 npm 包导出的是 ESM 规范的包,使用 module
如果 npm 包只在 web 端使用,并且严禁在 server 端使用,使用 browser。
如果 npm 包只在 server 端使用,使用 main
如果 npm 包在 web 端和 server 端都允许使用,使用 browser 和 main
其他更加复杂的情况,如npm 包需要提供 commonJS 与 ESM 等多个规范的多个代码文件,请参考上述使用场景或流程图
本文首发于 github 博客
如文章对你有帮助,你的 star 是对我最大的支持
其他文章:掌握甩锅技术: Typescript 运行时数据校验
还可以这么玩?超实用 Typescript 内置类型与自定义类型
插播广告:
深圳 Shopee 长期内推
岗位:前端,后端(要转go),产品,UI,测试,安卓,IOS,运维 全都要。
薪酬福利:20K-50K
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/104580.html
摘要:优化代码拆分从入口文件开始,递归地构建了整个应用的模块依赖图表,然后通常会将所有的模块打包成一个。 如果你还不知道什么是React,请点击这里github源码 安装Node.js 如果你还不知道什么是ECMAScript,请点击这里 如果你还不知道什么是Node.js,请点击这里 下载Node.js并安装;接着打开windows命令行窗口分别输入node -v及npm -v如下图所示,...
摘要:非官方字段集合官方字段请参考。下面介绍的是非官方字段,也就是各种工具定义的相关字段。详细参考相关字段设置项目的浏览器兼容情况。相关字段测试库。相关字段代码检查与优化。 package.json 非官方字段集合 package.json 官方字段请参考 https://docs.npmjs.com/files/package.json。下面介绍的是非官方字段,也就是各种工具定义的相关字段...
摘要:的定位属于预处理器吗还是属于后置处理器都不是,因为具体做的事取决于开发者使用了什么插件。这里做一个我觉得比较恰当的类比,中的相当于的中的,,等预处理器相当于,虽然不是完全合理,但是还是比较恰当。 前言 原谅我取这样的标题,我知道 postCss 对于大多数前端开发者来说早已经很熟悉了,但是楼主作为一个初出茅庐的前端er,还有好多的工具和技术没接触过,说来惭愧。虽然平时也喜欢使用css预...
摘要:的另一种形式测试踩坑之路代码覆盖率单元测试的代码覆盖率统计,是衡量测试用例好坏的一个的方法。 showImg(https://segmentfault.com/img/remote/1460000012564211?w=640&h=280); 项目地址: diana文档地址: http://muyunyun.cn/diana/ 造轮子的意义 为啥已经有如此多的前端工具类库还要自己造轮...
摘要:使用要给项目构建接入动态链接库的思想,需要完成以下事情把网页依赖的基础模块抽离出来,打包到一个个单独的动态链接库中去。接入已经内置了对动态链接库的支持,需要通过个内置的插件接入,它们分别是插件用于打包出一个个单独的动态链接库文件。 webpack优化 查看所有文档页面:全栈开发,获取更多信息。原文链接:webpack优化,原文广告模态框遮挡,阅读体验不好,所以整理成本文,方便查找。 ...
阅读 2992·2021-10-13 09:39
阅读 2692·2021-09-27 13:34
阅读 2030·2019-08-30 15:55
阅读 3259·2019-08-30 15:43
阅读 3630·2019-08-30 11:16
阅读 1748·2019-08-26 18:28
阅读 1282·2019-08-26 13:56
阅读 913·2019-08-26 13:35