当前位置: 首页 > 后端技术 > Node.js

在package.json中,你不知道browser、module、main字段的优先级

时间:2023-04-03 16:07:44 Node.js

browserVSmoduleVSmain。前端开发使用npm包是家常便饭,但是使用npm包难免会接触到package.json包配置文件。那么这里有一个问题,当我们在不同的环境中导入一个npm包的时候,会加载npm包的哪个文件呢?老司机们很快给出了答案:main字段指定的文件。但是,我们知道npm包其实分为:只允许在客户端使用的,只允许在服务端使用的,浏览器和服务端都可以使用的。如果我们需要开发一个同时兼容web端和服务端的npm包,需要在不同的环境下加载不同的npm包入口文件。很明显,一个main字段已经不能满足我们的需求了,这就引出了module和browser字段。.本文会讲到这几个字段的使用场景,以及这些字段同时存在时的优先级。文件优先级在讲package.json之前,先说说文件优先级。由于我们使用了ESM和commonJS两种模块规范,为了在node环境下原生执行ESM规范的脚本文件,.mjs文件应运而生。.当存在index.mjs和index.js等同名不同后缀的文件时,import'./index'或require('./index')会先加载index.mjs文件。即优先mjs>jsbrowser,module和main字段字段定义main:定义npm包的入口文件,浏览器环境和node环境都可以使用module:定义npm包的ESM规范入口文件,浏览器环境和node所有环境都可以使用浏览器:定义npm包在浏览器环境下的入口文件使用场景和优先级首先,我们假设npm包test有如下目录结构-----lib|--index.browser。js|--index.browser.mjs|--index.js|--index.mjs其中*.js文件使用commonJS标准语法(require('xxx')),*.mjs使用ESM标准语法(import'xxx')itspackage.jsonfile:"main":"lib/index.js",//main"module":"lib/index.mjs",//module//浏览器可以定义为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"//浏览器配置完成根据上面,那么其实我们package.json指定的entry可以有五种情况:mainmodulebrowserbrowser+cjsbrowser+mjs。下面说说具体的使用场景。webpack+web+ESM这是我们最常见的使用场景。我们通过webpack打包构建我们的web应用程序。模块语法使用ESM。当我们加载importtestfrom'test'时,实际加载的优先级是browser=browser+mjs>module>browser+cjs>main表示webpack会按照这个顺序搜索该字段指定的文件,直到找到为止。然而,实际情况可能比这更复杂。详情请参考流程图。影响优先级还是browser=browser+mjs>module>browser+cjs>mainwebpack+node+ESM/commonJS我们知道在使用webpack构建项目的时候,有一个target选项,默认是web,也就是web应用建设。当我们需要构建一些同构项目或者其他node项目时,需要将webpack.config.js的target选项设置为node来构建。importtestfrom'test'//orconsttest=require('test')优先级为:module>mainnode+commonJS直接通过nodetest.js执行脚本consttest=require('test')只有main字段有效.node+ESM通过--experimental-modules允许node执行ESM规范脚本(必须是mjs文件的后缀)`node--experimental-modulestest.mjsimporttestfrom'test'只有主字段有效。综上所述,如果npm包导出符合ESM的包,请使用module.如果npm包只在web端使用,严禁在服务端使用,就用浏览器吧。如果npm包只用在服务端,就用main如果允许web端和服务端都用npm包,就用browser和main其他比较复杂的情况,比如需要提供npm包commonJS、ESM文件等多种规范的多种代码,请参考上述使用场景或流程图