0%

package.json文件解析

概述

从我们接触前端开始,每个项目的根目录下一般都会有一个 package.json 文件,这个文件定义了当前项目所需要的各种模块,以及项目的配置信息(比如名称、版本、许可证等)。

当然大部分人其实并不关心 package.json 的配置,业务中应用的更多的是 dependencies 或 devDependencies 配置。

但当开发库并上传 npm 仓库时,package.json 的配置就至关重要了,如果理解关键属性并加以应用会使得开发和解决问题的效率大大提升。

接下来本文会详细解释一下每个字段的真实含义。

tips:可参考ant-design的 package.json 进行阅读

官方属性

package.json文件中最重要的就是nameversion字段,这两项是必填的。名称和版本一起构成一个标识符,该标识符被认为是完全唯一的。对包的更改应该与对版本的更改一起进行。

1.name

name必须小于等于 214 个字符,不能以.或_开头,不能有大写字母,因为名称最终成为 URL 的一部分因此不能包含任何非 URL 安全字符。 npm官方建议我们不要使用与核心节点模块相同的名称。不要在名称中加jsnode。如果需要可以使用engines来指定运行环境。

该名称会作为参数传递给 require,因此它应该是简短的,但也需要具有合理的描述性。


2.version

version必须可由 node-semver 解析,因为它会与 npm 作为依赖项捆绑在一起。


3.description

description是一个字符串,用于编写描述信息。
有助于在npm库中搜索的时候发现你的模块。


4.keywords

keywords是一个字符串组成的数组,有助于在npm库中搜索的时候发现你的模块。


5.homepage

项目的主页地址


6.bugs

用于项目问题的反馈 issue 地址或者一个邮箱。

1
2
3
4
"bugs": {
"url" : "https://github.com/owner/project/issues",
"email" : "project@hostname.com"
}

7.license

license是当前项目的协议,让用户知道他们有何权限来使用你的模块,以及使用该模块有哪些限制


8.author & contributors

author是具体一个人,contributors表示一群人,他们都表示当前项目的共享者。同时每个人都是一个对象。具有name字段和可选的urlemail字段。

1
2
3
4
5
"author": {
"name" : "xxx",
"email" : "xxx@xx.com",
"url" : "https://xxx.com/"
}

也可以写成一个字符串

1
"author": "xxx xxx@xx.com"

9.files

files属性的值是一个数组,内容是模块下文件名或者文件夹名,如果是文件夹名,则文件夹下所有的文件也会被包含进来(除非文件被另一些配置排除了)

可以在模块根目录下创建一个.npmignore文件,写在这个文件里边的文件即便被写在files属性里边也会被排除在外,这个文件的写法与.gitignore类似。


10.main

定义了 npm 包的入口文件,browser 环境和 node 环境均可使用


11.module

定义 npm 包的 ESM 规范的入口文件,browser 环境和 node 环境均可使用

优先级:module > main


12.browser

定义 npm 包在 browser 环境下的入口文件


13.bin

bin项用来指定每个内部命令对应的可执行文件的位置。如果你编写的是一个 node 工具的时候一定会用到 bin 字段。
当我们编写一个 cli 工具的时候,需要指定工具的运行命令,比如常用的 webpack 模块,他的运行命令就是

1
2
3
webpack。"bin": {
"webpack": "./bin/index.js",
}

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

在模块以依赖的方式被安装,如果存在bin选项。在node_modules/.bin/生成对应的文件, Npm会寻找这个文件,在node_modules/.bin/目录下建立符号链接。由于node_modules/.bin/目录会在运行时加入系统的PATH变量,因此在运行npm时,就可以不带路径,直接通过命令来调用这些脚本。

所有node_modules/.bin/目录下的命令,都可以用npm run [命令]的格式运行。在命令行下,键入npm run,然后按 tab 键,就会显示所有可以使用的命令。


14.repository

指定一个代码存放地址,对想要为你的项目贡献代码的人有帮助

1
2
3
4
"repository" : {
"type" : "git",
"url" : "https://github.com/npm/npm.git"
}

15.script

scripts 指定了运行脚本命令的 npm 命令行缩写,比如 start 指定了运行 npm run start 时,所要执行的命令。

1
2
3
"scripts": {
"start": "node ./start.js"
}

使用scripts字段可以快速的执行 shell 命令,可以理解为alias
scripts可以直接使用node_modules中安装的模块,这区别于直接运行需要使用npx命令。

1
2
3
4
5
6
"scripts": {
"build": "webpack"
}

// npm run build
// npx webpack

16.config

config字段用于添加命令行的环境变量。

1
2
3
{
"config": { "port": "8080" }
}

然后,在server.js脚本就可以引用 config 字段的值。

1
console.log(process.env.npm_package_config_port) // 8080

用户可以通过 npm config set 来修改这个值。

1
npm config set {name}:port 8000

17.dependencies & devDependencies

dependencies字段指定了项目运行所依赖的模块,devDependencies指定项目开发所需要的模块。

它们的值都是一个对象。该对象的各个成员,分别由模块名和对应的版本要求组成,表示依赖的模块及其版本范围。

当安装依赖的时候使用--save参数表示将该模块写入dependencies属性,--save-dev表示将该模块写入devDependencies属性。


18.peerDependencies

有时,你的项目和所依赖的模块,都会同时依赖另一个模块,但是所依赖的版本不一样。比如,你的项目依赖 A 模块和 B 模块的 1.0 版,而 A 模块本身又依赖 B 模块的 2.0 版。

大多数情况下,这不构成问题,B 模块的两个版本可以并存,同时运行。但是,有一种情况,会出现问题,就是这种依赖关系将暴露给用户。

最典型的场景就是插件,比如 A 模块是 B 模块的插件。用户安装的 B 模块是 1.0 版本,但是 A 插件只能和 2.0 版本的 B 模块一起使用。这时,用户要是将 1.0 版本的 B 的实例传给 A,就会出现问题。因此,需要一种机制,在模板安装的时候提醒用户,如果 A 和 B 一起安装,那么 B 必须是 2.0 模块。

peerDependencies 字段,就是用来供插件指定其所需要的主工具的版本。

1
2
3
4
5
6
{
"name": "chai-as-promised",
"peerDependencies": {
"chai": "1.x"
}
}

上面代码指定,安装 chai-as-promised 模块时,主程序 chai 必须一起安装,而且 chai 的版本必须是 1.x。如果你的项目指定的依赖是 chai 的 2.0 版本,就会报错。

注意,从 npm 3.0 版开始,peerDependencies 不再会默认安装了。


19.bundledDependencies

bundledDependencies指定发布的时候会被一起打包的模块.


20.optionalDependencies

如果一个依赖模块可以被使用, 同时你也希望在该模块找不到或无法获取时npm继续运行,你可以把这个模块依赖放到optionalDependencies配置中。这个配置的写法和dependencies的写法一样,不同的是这里边写的模块安装失败不会导致npm install失败。


21.engines

engines字段指明了该模块运行的平台,比如Node或者npm的某个版本或者浏览器。

1
{ "engines": { "node": ">=0.10.3 <0.12", "npm": "~1.0.20" } }

22.os

可以指定你的模块只能在哪个操作系统上运行

1
"os" : [ "darwin", "linux", "win32" ]

23.cpu

限制模块只能在某种架构的cpu下运行

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

24.private

如果这个属性被设置为truenpm将拒绝发布它,这是为了防止一个私有模块被无意间发布出去。

1
"private": true

25.publishConfig

这个配置是会在模块发布时生效,用于设置发布用到的一些值的集合。如果你不想模块被默认标记为最新的,或者默认发布到公共仓库,可以在这里配置 tag 或仓库地址。

通常publishConfig会配合private来使用,如果你只想让模块被发布到一个特定的npm仓库,如一个内部的仓库。

1
2
3
4
5
6
"private": true,
"publishConfig": {
"tag": "1.0.0",
"registry": "https://registry.npmjs.org/",
"access": "public"
}

26.preferGlobal

preferGlobal的值是布尔值,表示当用户不将该模块安装为全局模块时(即不用–global 参数),要不要显示警告,表示该模块的本意就是安装为全局模块。

1
"preferGlobal": false

更多请参考package.json 的官方属性

额外属性

1.types | typings

定义一个针对 TypeScript 的入口文件


2.unpkg

让 npm 上所有的文件都开启 cdn 服务。

1
2
3
{
"unpkg": "dist/antd.min.js"
}

当你使用省略的 url https://unpkg.com/antd 时,便会按照如下的方式获取文件:

1
2
3
4
5
6
7
# [latestVersion] 指最新版本号,pkg 指 package.json

# 定义了 unpkg 属性时
https://unpkg.com/jquery@[latestVersion]/[pkg.unpkg]

# 未定义 unpkg 属性时,将回退到 main 属性
https://unpkg.com/jquery@[latestVersion]/[pkg.main]

3.browserslist

设置项目的浏览器兼容情况。

1
2
3
{
"browserslist": ["> 1%", "last 2 versions"]
}

4.webpack

1
2
3
{
"sideEffects": true | false
}

声明该模块是否包含 sideEffects(副作用),从而可以为 tree-shaking 提供更大的优化空间。


5.exports

exports 字段提供了一种方法来为不同的环境和 JavaScript 风格公开您的包模块,同时限制对其内部部分的访问。
具体用法请参考官方文档


更多请参考package.json 的额外属性

参考资料