package.json 文件
一、package.json 的作用
Node 项目根目录中的 package.json 文件包含项目的名称、版本、描述和相关依赖等可读元数据和功能元数据。
{
"name": "xx-project",
"version": "1.0.0",
"author": "Leophen",
"contributors": [
{
"name": "xx",
"email": "xx@example.com",
"url": "https://www.xx.com/#team"
}
],
"description": "This is xx-project",
"keywords": ["node.js", "javascript"],
"repository": {
"type": "git",
"url": "https://github.com/xx/xx.git"
},
"engines": { "node": "0.10.x" },
"license": "MIT",
"bugs": { "url": "http://path/to/bug", "email": "bug@example.com" },
"main": "src/index.js",
"scripts": {
"start": "node index.js",
"dev": "nodemon",
"lint": "eslint **/*.js"
},
"dependencies": {
"express": "latest",
"mongoose": "~3.8.3"
},
"devDependencies": {
"eslint": "^5.16.0",
"bower": "~1.2.8"
}
}
package.json
文件使 npm 可以启动项目、运行脚本、安装依赖项、发布到 NPM 注册表以及许多其他有用的任务。npm CLI 也是管理 package.json
的最佳方法,它有助于在项目的整个生命周期内生成和更新 package.json
文件。
package.json
会在项目的生命周期中扮演多个角色,其中某些角色仅适用于发布到 NPM 的软件包。
另外,项目必须包含 package.json
才能从 NPM 安装软件包。
二、package.json 的字段
name
项目的名称。
它不能超过 214 个字符,只能是小写字母,并且必须是 URL 安全的(允许连字符和下划线,但 URL 中不允许使用空格或其他字符)如果将软件包发布到 NPM,则 name 属性是必需的,并且必须是唯一的。
version
项目的版本号。
author
author 是 people 字段,只供一个人使用,可以是 "Name" 格式的字符串,也可以是具有 name,email,url 字段的对象,email 和 url 都是可选的。
contributors
contributors 和 author 类似,但 contributors 可以由多个人组成。这些字段是列出公共项目的联系人以及与贡献者共享信用的有用方法。
description
项目的描述,便于用户在 npm 上搜索到项目。
keywords
便于用户在 npm 上搜索到项目的字符串数组。
homepage
项目 url 主页,例如:
"homepage": "https://www.leophen.cn"
files
描述软件包作为依赖项安装时要包括的文件数组。
以下文件无论是否设置,总是包含:
"package.json"
"README"
"CHANGES" / "CHANGELOG" / "HISTORY"
"LICENSE" / "LICENCE"
"NOTICE"
"The file in the “main” field"
以下文件总是被忽略:
".git"
"CVS"
".svn"
".hg"
".lock-wscript"
".wafpickle-N"
".*.swp"
".DS_Store"
"._*"
"npm-debug.log"
".npmrc"
"node_modules"
"config.gypi"
"*.orig"
"package-lock.json(use shrinkwrap instead)"
repository
代码存放地方。对于开源项目,可以是以 Git 作为版本控制系统的 GitHub 或 Bitbucket。
engines
表示该模块运行的平台,比如 Node 的某个版本或者浏览器,也可以指定适用的 npm 版本。
license
项目许可证,让使用者知道如何使用此项目。通常是许可证的标识符代码—— MIT 或 ISC 之类的字符串,代表 MIT 许可证和 ISC 许可证。如果不想提供许可证或不想授予使用私有/未发布软件包的权限,则可以将 UNLICENSED 作为许可证。
bugs
项目问题反馈的 url 或报告问题的 email。
main
主文件,即项目的入口点,用于启动项目的文件。通常是项目根目录的 index.js
,如果项目名称叫 foo。那么 require("foo")
将返回 index.js
的内容,路径相对软件包根目录。
browser
如果要在客户端使用模块,则应使用 browser 字段来代替 main 字段。
scripts
指定了运行脚本命令的 npm 命令行缩写,例如 start 指定了运行 npm run start
所要执行的命令。
dependencies
指定项目运行所依赖的模块,它包含的依赖包是需要发布到生产环境中的。
依赖版本中的插入符(^
)和波浪符(~
)是 SemVer 中定义的版本范围的表示法。
常见的版本限定如下:
- 没加符号:例如 1.2.2,表示只安装 1.2.2 版本。
- 加插入符(
^
):例如 ˆ1.2.2,表示安装 1.x.x 的最新版本(不低于 1.2.2)- 加波浪符(
~
):例如 ~1.2.2,表示安装 1.2.x 的最新版本(不低于 1.2.2)
devDependencies
指定项目运行所依赖的模块,它包含的依赖包只在开发时使用,不用于生产环境。
peerDependencies
指定当前组件所需要的依赖及依赖的版本。如果项目中安装了其他版本的同一依赖,会提示报错,可以避免同一个依赖被重复安装。
使用了 peerDependency
后:
- 如果用户显式依赖了核心库,则可以忽略各插件的
peerDependency
声明; - 如果用户没有显式依赖核心库,则按照插件
peerDependencies
中声明的版本将库安装到项目根目录中; - 当用户依赖的版本、各插件依赖的版本之间不相互兼容,会报错让用户自行修复;
举个例子:
{
"name": "b",
"peerDependencies": {
"a": "1.x"
}
}
上面代码指定,安装 b
模块时,依赖 a
必须一起安装,而且 a
的版本必须是 1.x。如果项目指定的依赖是 a
的 2.0 版本,就会报错。
再举个例子,假设一个项目有如下依赖项:
{
"dependencies": {
"a": "1.0.0",
"b": "1.0.0",
"c": "1.0.0"
}
}
如果 b 和 c 都各自有依赖项 a,那么下载依赖后的项目目录是这样的:
├── project
│ └── node_modules
│ ├── a
│ ├── b
│ │ └── nodule_modules
│ │ └── a
│ └── c
│ │ └── nodule_modules
│ │ └── a
可以看到依赖 a 会被重复安装 3 次。这时就可以使用 peerDependencies
,它可以避免相同的依赖被重复安装。
现在只需要在 b 和 c 的 package.json
文件加上以下代码:
{
"peerDependencies": {
"a": "1.0.0"
}
}
这样在安装时就可以避免重复安装依赖了。现在下载依赖后的目录为:
├── helloWorld
│ └── node_modules
│ ├── a
│ ├── b
│ └── c
而且当主项目的 a 依赖项和 b、c 安装的 a 依赖项版本不同时会报错。
bundledDependencies
定义一个数组,会在发布时将定义的模块一起打包。用于需在本地保存 npm 包或者下载单个文件时可用。例如:
{
"name": "awesome-web-framework",
"version": "1.0.0",
"bundledDependencies": ["renderized", "super-streams"]
}
运行 npm pack
命令会得到 awesome-web-framework-1.0.0.tgz。
执行 npm install awesome-web-framework-1.0.0.tgz
将在新项目中安装 renderized 和 super-streams 这两个依赖项。
optionalDependencies
若希望在包找不到或者安装失败时,npm 继续运行,可将该包放在 optionalDependencies 对象中。optionalDependencies 会覆盖 dependencies 中同名的,所以最好只放在一个地方。
config
用于添加命令行的环境变量。
{
"name": "foo",
"config": { "port": "8080" },
"scripts": { "start": "node server.js" }
}
server.js
中使用 process.env.npm_package_config_port 来获取 port
。
用户可以通过执行 npm config set foo:port 80
来覆盖该命令。
bin
指定各个内部命令对应的可执行文件的位置。例如:myapp 里面包含
"bin": {
"someTool": "./bin/someTool.js"
}
上面代码指定,someTool
命令对应的可执行文件为 bin
子目录下的 someTool.js
。当本地安装 myapp
时,npm 会寻找这个文件,在 ./node_modules/.bin/ 目录下建立符号链接。在上面的例子中,someTool.js
会建立符号链接 ./node_modules/.bin/someTool。由于 ./node_modules/.bin/ 目录会在运行时加入系统的 PATH
变量,因此在运行 npm 时,就可以不带路径,直接通过命令来调用这些脚本。
所有 node_modules/.bin/ 目录下的命令,都可以用 npm run [命令]
的格式运行。bin 中引用的文件需以 #!/usr/bin/envnode 开头。
os
指定你的项目将运行在什么操作系统上。
cpu
指定你的项目将运行在什么 cpu 架构上。
private
如果设置为 true, 那么 npm 会拒绝发布它。