当前位置: 首页 > 科技观察

这还是我最熟悉的package.json吗?

时间:2023-03-23 10:42:01 科技观察

前言上次npminit@vitejs/app的背后,只是npmCLI[1]的冰山一角,提到我主要从两大方向回顾npm,所以本文继续说说package.json的知识。经过这一轮的审核,我也发现了很多不足之处。之前对常用的命令和配置都比较熟悉,没想到npm还有更多新玩法。实际解决别人的问题。npm的配置比较多,具体可以参考官方的package.json文档[2]。看完文档,我跳过了一些基本的配置项,总结了一些我觉得比较有用的配置项。常用配置项filesfiles定义了npminstall后node_modules中应该包含哪些文件。当然,有些文件是自动暴露的,无论你是否配置文件,例如:package.jsonREADME/CHANGELOG/LICENSE...许多库定义文件以避免不必要的文件暴露给node_modules。这是vite中的配置:{"files":["bin","dist","client.d.ts"]}之前不知道这个配置,导致我发布了一个npm组件vue-awesome-progress[3]源码部分暴露了,虽然这个没什么影响,但是开源了。但是这样也增加了别人下载资源的量,也是一种浪费。因此,专业的做法是添加文件配置。binbin列出可执行文件,表明你的包将向外界提供哪些脚本。通过install安装这个包时,如果是全局安装-g,会将bin中列出的可执行文件添加到PATH变量中(全局可执行);如果是本地安装,会进入node_modules/.bin/目录。bin在一些CLI工具中经常使用,例如VueCLI。开发npm包时,要求发布的可执行脚本以#!/usr/bin/envnode开头。为什么?查了一下,发现是用来表示脚本文件应该使用node.js来执行的。main、browser、module这三个配置对我们影响很大。main域决定了当其他的require('xxx')时引用了哪个模块对象。不设置主字段时,默认值为index.js。如果你开发的包是针对浏览器的,那么用浏览器指定入口文件是最好的选择。module表示你开发的包支持ESM,并指定一个ESM入口。如何使用这三个字段是相当有学问的。这里推荐一篇你还不知道的package.json中浏览器、模块、主要字段优先级的文章[4],非常详细。长图警告!scriptsscripts基本天天用,但是你用过它的hook脚本吗?如果你没有使用过它,你可以尝试一下。在组织脚本流程时非常有用!pre:在脚本执行之前执行,比如prebuild可以做一些打包前的准备工作。post:在一个脚本执行完后执行,比如postbuild,打包后可以做一些收尾工作。configconfig配置的参数xxx可以在脚本中以npm_package_config_xxx的形式引用,比如port。{"config":{"port":"8080"}}依赖相关的dependencies可以理解为生产依赖,通过npminstall--save安装的依赖包会进入dependencies。devDependenciesdevDependencies可以理解为开发环境依赖,通常是一些工具包,比如webpack、babel等,通过npminstall--save-dev安装的依赖会进入devDependencies。然而,当与一些构建工具结合使用时,我们常常会感到困惑。比如我安装了一个package到devDependencies中,但是不小心在项目中引用了它,最后被webpack打包到构建结果中。这里发生了什么?建议结合上一篇npminstall章节[5]一起阅读。peerDependencies我是package-a,如果你安装我,你必须安装我的peerDependencies。让“包人”升级package-a的依赖到自己的node_modules,避免“包人”和package-a都需要同一个依赖(如vue)时重复安装。这在开发组件或库时很常见。注意,如果一个npm包的开发者声明了peerDependencies,开发环境中package目录下的npminstall不会在node_modules中安装这些依赖,所以往往需要devDependencies。比如我开发一个组件,不想在发布到npm时包含vue代码,需要外部提供vue,所以我在peerDependencies中定义vue无可厚非。但是在开发组件的时候,一般需要在本地开发环境中运行一个demo来试一下效果。这个时候依赖vue,所以需要在devDependencies中安装vue。我看到vue-router是这样做的,所以在自己开发组件的时候也学了这个trick。bundledDependenciesbundledDependencies和上面的依赖不一样,配置的不是键值对的形式,而是一个数组。{"bundledDependencies":["vue","vue-router"]}会在运行npmpack时将对应的依赖包打包到tgz文件中。我用的不多,具体的细节我也不清楚。主要是tgz包直接用npminstall安装的场景比较少。只要有一个概念。optionalDependenciesoptionalDependencies用于配置可选依赖项。即使这样配置,也必须在代码中进行判断(保护),否则运行起来报错就不好玩了。try{varfoo=require('foo')varfooVersion=require('foo/package.json').version}catch(er){foo=null}题外话仔细看了package.json文档,还是解决为整个我的很多困惑也为我开发npm组件提供了很多帮助。如果你想了解更多细节和实战,不妨打开我的项目vue-awesome-progress[3]看看,希望对你有所帮助!