-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
package.json 中 你还不清楚的 browser,module,main 字段优先级 #8
Comments
这个可有什么官方文档出处? |
@terrilltang 至于这几个字段的优先级,我好像没找到详细的官方说明,所以我才自己测试下进行归纳总结。 |
webpack/webpack#5673 (comment) 另外这里有webpack的部分代码(搜 按我的理解,正常来说main指向cjs,module指向mjs,当一个包兼容浏览器端与node端,但output不同时(比如同构应用),才使用 browser 指向兼容浏览器的版本,这种情况main和module两个都需要兼容版本,因此browser支持对象的格式提供一个映射关系。 |
测了下webpack的模块选择优先级可以根据resolve.mainFields配置的顺序进行调整,参见https://webpack.docschina.org/configuration/resolve/#resolve-mainfields |
试了browser,貌似只能使用string,不能使用对象 |
@SunshowerC 请问博主有考虑webpack resolve.mainFields配置吗。 |
@colgin 流程图确实不够全,实际上不存在 module 时会再判断有没有 browser 的,解析顺序是 browser > module > main,所以有 browser 无 module 的场景下是用 browser 的。 |
问一个看似不大相关的问题,
|
@Zippowxk 第三种方式可能会报错,你项目工程里面不一定有你test.esm.js的运行环境。 |
有道理 但是第二种方式报错,就是因为打包环境不一致导致的吗?比如eslint 和 babel的preset不一致 |
…) format, unless you set `type: 'module'` in package.json, then it become a ES modules (esm) We use 'cjs' format for 'main' since it is by default, then use 'esm' format for 'module' For the file name, 'cjs' to be '.js', 'esm' to be '.mjs' (reference: SunshowerC/blog#8) Set 'browser' with 'umd' format, for browser use (maybe through https://unpkg.com/).
mark |
讲的很清楚,谢谢 |
m |
已收到,谢谢~~
|
总结的时有错误: 错误:如果 npm 包在 web 端和 server 端都允许使用,使用 browser 和 main |
Mark |
已收到,谢谢~~
|
前排围观 |
”总结的时有错误“可以修改总结部分吗 |
也就是说,优先级 mjs > js,这个结论是错误的 |
browser
VSmodule
VSmain
browser
,module
和main
字段browser
VSmodule
VSmain
前端开发中使用到
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
有以下目录结构其中
*.js
文件是使用 commonJS 规范的语法(require('xxx')
),*.mjs
是用 ESM 规范的语法(import 'xxx'
)其 package.json 文件:
根据上述配置,那么其实我们的
package.json
指定的入口可以有main
module
browser
browser+cjs
browser+mjs
这 5 种情况。
下面说下具体使用场景。
webpack + web + ESM
这是我们最常见的使用场景,通过
webpack
打包构建我们的 web 应用,模块语法使用 ESM当我们加载
实际上的加载优先级是
browser
=browser+mjs
>module
>browser+cjs
>main
也就是说 webpack 会根据这个顺序去寻找字段指定的文件,直到找到为止。
然而实际上的情况可能比这个更加复杂,具体可以参考流程图
webpack + web + commonJS
事实上,构建 web 应用时,使用
ESM
或者commonJS
模块规范对于加载优先级并没有任何影响优先级依然是
browser
=browser+mjs
>module
>browser+cjs
>main
webpack + node + ESM/commonJS
我们清楚,使用 webpack 构建项目的时候,有一个 target 选项,默认为 web,即进行 web 应用构建。
当我们需要进行一些 同构项目,或者其他 node 项目的构建的时候,我们需要将
webpack.config.js
的target
选项设置为node
进行构建。优先级是: module > main
node + commonJS
通过
node test.js
直接执行脚本只有 main 字段有效。
node + ESM
通过
--experimental-modules
可以让 node 执行 ESM 规范的脚本(必须是 mjs 文件后缀)`node --experimental-modules test.mjs
只有 main 字段有效。
总结
npm
包导出的是 ESM 规范的包,使用 modulenpm
包只在 web 端使用,并且严禁在 server 端使用,使用 browser。npm
包只在 server 端使用,使用 mainnpm
包在 web 端和 server 端都允许使用,使用 browser 和 mainnpm
包需要提供 commonJS 与 ESM 等多个规范的代码文件,请参考上述使用场景或流程图The text was updated successfully, but these errors were encountered: