测一测 package.json 配置你了解多少?

703 阅读9分钟

前奏

package.json是我们最常见的配置文件,在工作中经常与其打交道。它可以帮助该 npm 包的使用者能更好的理解和使用该 npm 包。小柒详细的梳理了一下package.json中各个配置。

必须属性

name

name 是一个包的唯一标识,不得和其他包名重复,必须小于等于214个字符,不能以 . 和 _ 开头,不能包含大写字母。

我们可以通过执行 npm view packageName 可以查看包名是否被占用。

version

格式按照主版本号.次版本号.修订号的形式。如果是不稳定可以发内部版本(alpha)、公测版本(beta)、候选版本(rc)(2.0.1-alpha)。参与过公司内部的组件库构建的小伙伴们应该最清楚不过了。

描述信息

description

该字段以字符串形式描述项目。

keywords

该字段以字符串数组的形式描述这个项目的关键词。

{
  "keywords": ['lint', 'react','ts']
}

写好 descriptionkeywords 可以使我们的 npm 包获得更多曝光。

author

描述该 npm 包作者。

  {
   "author":'xiaoqi'
   // 或者
   "author": {
     "name" : "xiaoqi",
     "email" : "xxxxx@xx.com",
     "url" : "https://juejin.cn/user/1275089220808040"
   }
  }

contributors

描述项目贡献者。与 author 不同的是它是数组形式。

homepage

以字符串形式描述项目的主页地址。

repository

描述代码仓库地址。

{
  "repository": "https://github.com/facebook/react.git"
  // 或者
  "repository": {
    "type": "git",
    "url": "https://github.com/facebook/react.git"
  }
 }

bugs

描述项目提交问题的地址。

{
 "bugs": { 
    "url" : "https://github.com/facebook/react/issues",
    "email" : "xxxxx@xx.com"
  }
}

依赖配置

注意:声明在 dependenciesdevDependencies 中的包,与打包工具将不将这些包打包没有关系。

dependencies:

声明项目在生产环境时所需要的依赖包。安装某个依赖包时,需判断生产环境下是否需要,再进行安装。

npm i xxx 或 npm i xxx  --save 或 npm i xxx -S (小柒推荐)

该值是一个对象,记录了依赖包的名称和版本号。

dependencies: {
  "clsx": "1.1.1"
  "swiper": "^6.4.8"
}

前面说过,版本号一般遵循 主版本号.次版本号.修订号。我们安装的 npm 包的时候会碰到这样几种形式的版本号。

  • latest: 安装最新版本

  • ^: 比如上述的 swiper 安装 6.x.x 的最新版本,但是不低于6.4.8 。这种形式是小柒在所开发的项目中,见的最多的一种形式。

  • ~:比如 ~6.4.8。表示安装6.4.x 的最新版本,但是不低于6.4.8。

  • 固定版本号

上面的 clsx 就是固定版本号。有时候某个依赖包的最新版本有问题的时候,可以指定安装固定的稳定版本。

devDependencies

声明项目在开发时才需要用到的依赖包。比如 eslinttypescriptviteprettier 这些都是开发是采用的辅助包,生产环境下不需要这些代码。

如果当前项目被当作依赖包被引用时,在对方使用 npm install --production 时不会安装devDependencies 中的包。

npm i xxx --save-dev 或 npm i xxx -D
dependencies: {
    "eslint": "latest",
    "typescript": "^4.4.4"
}

peerDependencies

适用的场景一般是插件或者组件库。

比如要在项目 A(主项目) 中实现某个功能,而这个功能相对独立且复杂的时候,我们可以把这部分功能提出来新起一个项目 B 来维护它,在项目 A 中以依赖包的形式去引入项目 B(依赖项目)。这和我们在项目引入别人的ui组件库是一样的道理。

那 peerDependencies 可以帮我们解决什么问题呢?

避免项目 A 安装了与项目B所依赖的核心包版本不一致的问题

比如项目 B 必须安装 reactreact-dom 并且必须是 16.8.0 以上的才能运行,否则就会报错。那如果项目A中未安装或者安装了低版本的 reactreact-dom 依赖包,这样就会错误的发生。

 "peerDependencies": {
    "react": ">=16.8.0",
    "react-dom": ">=16.8.0"
  }

我们在项目 B 的 package.json文件下的添加 peerDependencies 字段,并声明所依赖的核心包及版本号(dependencies 中不再声明,如果声明了可以忽略 peerDependencies 字段)。这样相当于告知了项目A:“你要想安装我,就必须安装 reactreact-dom 这两个包,并且版本要大于16.8.0,否则你可能会报错”。

小柒在写业务的时候如果项目A够大,项目B生产环境所依赖的包项目A基本都会安装,那小柒一般会将这些依赖包都写入 peerDependencies 字段, dependencies 中不再声明这些依赖包,直接让项目 A 去安装。

bundledDependencies

如果希望某些依赖包在打包发布的时候也被一起打包,可以在 bundledDependencies 中声明该包。注意这些包提前是在 dependencies 中声明过的。

{
  "name": "my_test",
  "version": "1.0.0",
  "bundledDependencies": [
    "react", "react-dom"
  ],
}

npm pack 后会生成 my_test-1.0.0.tgz。这样 reactreact-dom 也会在 npm install my_test-1.0.0.tgz 时被下载。

optionalDependencies

另一种 dependencies。如果在项目中,npm在安装dependencies过程中可能因为出错会退出安装,对于在 optionalDependencies 中声明的模块的来说,即使出错了,也不会导致 npm install 中断退出。另外 optionalDependencies 会覆盖 dependencies 中的同名依赖包,不需要在两个地方都声明。

engines

描述模块运行的环境。这个场景比较适用于维护老项目,比如该项目对 node 版本 和 npm 版本都有要求,否则运行不起来。这样在 engines 中声明之后,会提醒开发者升级到指定的版本。

"engines": {
    "node": ">= 11"
    "npm": "~6.0.1"
  }

脚本配置

scripts

用于配置运行脚本命令的缩写。

"scripts": {
  "dev": "node index.js",
}

这样可以通过 npm run dev 来运行。该字段的好处是大大提升开发效率。

config

配置脚本中使用的环境变量。

{
  "name" : "my_test",
  "config": {"port": 3000}
}

这样在 scripts 的脚本中就可以使用 process.env.npm_package_config_port 来获取这个值。我们可以通过 nom config set 来修改这个值。

npm config set my_test:port 8000

目录、文件相关

files

该字段以数组的形式表示描述了发布 npm 包时所推送的文件列表。

{
    "files": [
      "dist",
      "lib",
      "es"
    ]
}

如果发布时,某些文件不想被发布,可以在根目录配置一个.npmignore 文件来排除一些文件(类似于.gitignore文件),此时即使文件名被写入在 files 字段中也不会被发布。如果有.gitignore文件,没有.npmignore 文件将会使用.gitignore文件来代替。

main

指定程序加载的入口文件,在 browsernode 环境中都可以使用。没有指定该字段,默认是根目录的 index.js 文件。如果我们的包以 npm 形式被安装,那么 require 导入的 npm 包时,实际上就是导入的 mian 字段指定文件中的 module.export 暴露出来的模块。

"main": "./src/index.js"

browser

如果 npm 包只能在 browser 端使用,使 browser 字段代替 main 字段来指定入口文件。

{
   "browser": "./src/index.js" 
}

bin

指定命令行工具的入口文件。这个字段在编写 node 工具的时候常常会用到,比如常见的 cli 工具。比如现在有一个 my-cli 的 工具,其 package.json 中的 bin 字段为:

{
 "bin": {
    "my-cli": "./bin/index.js"
  }
}

当我们执行 my-cli 命令的时候就会执行bin/index.js文件中的代码。

如果是全局安装 my-cli 包,会在 /usr/local/bin 下 创建一个以 my-cli 为名字的 symlink,指向全局安装的 my-cli 包的/bin/index.js 文件,可以直接使用 my-cli 命令来运行。

如果是本地安装 my-cli 包, 会在 node_modules/.bin下建立名字为 my-cli 的symlink,执行本地安装的 my-cli 包的 /bin/index.js 文件。由于 node_modules/.bin/ 目录会在运行时加入系统的 PATH 变量,可以直接使用 npm run my-cli 运行。(所有 node_modules/.bin/目录下的命令,都可以用npm run xx 的格式运行。)

man

用来给 Linux 下的 man 命令查找文档地址,是个单一文件或者文件数组。man 文件必须以数字结尾,或者如果被压缩了,以 .gz 结尾。数字表示文件将被安装到 man 的哪个部分。

{
  "name": "my_test",
  "version": "1.1.0",
  "description": "",
  "main": "index.js",
  "man": "./man/doc.1"
}

通过 man my_test 命令可以 ./man/doc.1 文件的内容。

directories

该字段用来规范项目的目录。一个 node 模块是基于 CommonJS 模块化规范实现的,严格按照 CommonJS 规范,项目目录下除了 package.json 文件以外,还需要包含以下目录:

  • bin: 存放可执行二进制文件的目录

  • lib:存放js代码的目录

  • doc:存放文档的目录

  • test:存放单元测试用例代码的目录

    ....

在实际项目中我们可能没有严格按照上面的规范来命名,此时可以通过使用 directories 字段来指定项目的目录结构与上述规结构的对应关系。

 "directories": {
    "lib": "src/lib/",
    "bin": "src/bin/",
    "man": "src/man/",
  }

发布配置

preferGlobal

如果你的 npm 包是需要全局安装,可以将这个字段设置为true,如果用户在本地安装了,会给出警告。

private

如果设置 private 为 true,可以防止将私有库发布到 npm 服务器。

{
  "private": true
}

如果只想将包发布到某个私有的 npm 源或者只想发布某个 tag,可以配合 publishConfig 字段来配置相关信息。

publishConfig

{
    "private": true,
    "publishConfig": {
      "tag": "1.1.0",
      "registry": "https://registry.npmjs.org/",
      "access": "public"
    }
}

更多配置 npm.config

os

这个字段可以告知用户该 npm 包可以在什么操作系统使用。

"os": ["linux"]
"os": ["!win32"] // 禁用win32

cpu

os 类似,可以用 cpu 属性更精准的告知用户使用该包的 cpu 环境。

"cpu" : [ "x64", "ia32" ]

license

用于指定开源协议。不同的协议表示使用你代码的人拥有的的权利。作者可以根据自己的作品选择合适的协议,为使用者开放哪些权限。

"license": "MIT"
  • MIT :只要用户在项目副本中包含了版权声明和许可声明,他们就可以拿你的代码做任何想做的事情,你也无需承担任何责任。
  • Apache :类似于 MIT ,同时还包含了贡献者向用户提供专利授权相关的条款。
  • GPL :修改项目代码的用户再次分发源码或二进制代码时,必须公布他的相关修改。

第三方配置

还有其他比较常用的字段: typingseslintConfiggitHookslint-staged 等,但非官方所出的字段,小柒这里不展开。

尾声

参考文章