前言
之所以写下这篇文,是因为前两天忽然发现,package.json里的版本号我好像就没注意过了,一会~开头,一会^开头,都是个啥?然后仔细回想了下发现我好像并没有真的了解过这玩意,每次打开个项目都是npm install一波敲敲启动命令就完事了。事后深刻反思了下觉得这样并不好万一某天来个人问你这里的XX是啥意思你都说不上来那多尴尬,于是就有了这篇文。
正文
1. npm
在介绍package.json前,需要先介绍一下npm。npm就是一个包含了很多Javascript包(package)的公有仓库(registry),开源开发者们可以贡献包,也可以在自己的项目中下载包。
有关package和modules的描述可以查看官方文档(这波懒得翻译了)
2. package.json
package.json是用来管理包的。要将一个包发布到npm中,必须要包含一个package.json文件。
package.json文件的作用:
- 列举出你的项目所依赖的包;
- 明确你的项目中可以使用的包的版本;
- 让你的包能够进行二次开发,更加容易和其他开发者分享;
创建package.json
创建方式有两种,通过命令行创建或者直接创建默认的package.json文件。
命令行: 进入项目目录-> npm init,然后通过命令行交互进行创建即可。
自定义创建package.json的命令行交互:可参考init-package-json
创建默认文件:可以使用当前目录内抽取的信息直接生成默认的package.json文件。进入项目目录-> npm init --yes | npm init -y
我们也可以配置初始化命令的配置项来设置默认值:
> npm set init.author.email "example-user@example.com"
> npm set init.author.name "example_user"
> npm set init.license "MIT"
3. 配置项
name
如果你要发布你的包,那么配置name和version字段是必须要填写且十分重要的;如果并不需要发布,那么name和version是可选的。
对于name和version字段有一些限制:
- name不能大于214个字符。如果是作用域包,也包含它的作用域。
- 作用域包的name可以以
.或者_开头。非作用域包的话是不允许的。 - 新包的name中不能包含大写字母。
- name最终会成为URL/命令行中的参数/文件名的一部分,因此name中不能包含非URL安全的字符。
version
对于要发布的包来说,version和name一样重要。version必须能够被node-semver解析。
description
description能够帮助人们使用npm search搜索到你的包。
keywords
keywords是一个字符串数组。和description一样能够帮助人们使用npm search搜索到你的包。
homepage
链接到项目主页的url。
"homepage": "https://github.com/owner/project#readme"
bugs
链接到项目issue的url or 提issue的邮箱地址。
{
"url" : "https://github.com/owner/project/issues",
"email" : "project@hostname.com"
}
两个值都是可选的,如果你只想用一个url,直接指定bugs的值为url字符串即可,不需要对象。
license
包应该指定一个license,这样其他用户就能够知道你的包可以如何使用,有哪些限制。
{
"license" : "BSD-3-Clause"
}
在一些旧的包中license是使用对象or对象数组声明的,现在已经不推荐使用了。
author, contributors
作者和贡献者们。可以用一个包含name字段的对象描述,url和email可选。
{
"name" : "Barney Rubble",
"email" : "b@rubble.com",
"url" : "http://barnyrubble.tumblr.com/"
}
或者可以简写到一个字符串中,npm会自动解析:
{
"author": "Barney Rubble <b@rubble.com> (http://barnyrubble.tumblr.com/)"
}
main
main字段指定了项目的入口。
browser
如果你的模块是用在客户端上的,那么应该指定browser字段而不是main字段。
bin
bin字段包含了一组命令到本地文件名的映射。安装包的时候,对于全局安装npm会创建一个文件到prefix/bin的符号链接,而对于局部安装,npm会创建文件到./node_modules/.bin/的符号链接。
{
"bin": {
"myapp": "./cli.js"
}
}
当我们安装myapp的时候,它就会创建一个从cli.js到/usr/local/bin/myapp的符号链接。
如果你的包中只有一条可执行命令并且命令名称和报名相同,那么就可以直接用字符串来声明:
{
"name": "my-program",
"version": "1.2.5",
"bin": "./path/to/program"
}
repository
指定了代码仓库的位置。
scripts
scripts属性是一个字典,其中包含了在包生命周期的不同时间运行的脚本命令。键是生命周期事件,值是在该点运行的命令。详见Scripts。
dependencies
dependencies是一个对象,对象中包含了包名到版本范围的映射。版本范围是一个具有一个或多个空格分隔的描述字符串,dependencies也可以用tarball或git URL标识。
注意:请不要将测试、编译或者其他在开发阶段使用的工具放在dependencies中。
版本范围说明:详见node-semver:README Versions部分。
相关阅读:语义化版本号
摘取一部分常见版本范围说明:
| 操作符 | 意义 | 说明 |
|---|---|---|
| < | 小于 | <1.2.7将匹配版本1.2.6、1.0.1、0.0.2,但不匹配版本1.2.7、2.0.0等 |
| <= | 小于等于 | <=1.2.7将匹配版本1.2.7、1.2.6,但不匹配版本1.2.8、2.0.0等 |
| > | 大于 | >1.2.7将匹配版本1.2.8、2.0.0,但不匹配版本1.2.7、1.0.0等 |
| >= | 大于等于 | >=1.2.7将匹配版本1.2.7、2.0.0,但不匹配版本1.2.6、1.0.0等 |
| ~ | 匹配次要版本 | ~1.2.3:= >=1.2.3 <1.(2+1).0:= >=1.2.3 <1.3.0-0 ~1.2:= >=1.2.0 <1.(2+1).0:= >=1.2.0 <1.3.0-0 ~1:= >=1.0.0 <(1+1).0.0:= >=1.0.0 <2.0.0-0 |
| ^ | 匹配兼容版本 | ^2.3.1:与2.3.1版本兼容即>=2.3.1 < 3.0.0,不改变大版本号 |
devDependencies
和测试、编译或者其他在开发阶段使用的相关工具应该放在devDependencies中。
peerDependencies
在某些开发场景下,你的包需要某些依赖的支持,但是没必要去安装,因为包的宿主会去安装这些依赖,这时就可以用peerDependencies去声明一下需要依赖的包和版本,如果出问题npm就会有警告来提醒使用者去解决版本冲突问题。
engines
可以通过engines来指定包运行node版本,或者指定哪些版本的npm可以正确运行你的程序:
{
"engines": {
"node": ">=0.10.3 <15",
"npm": "~1.0.20"
}
}
os
可以用来指定你的程序运行的操作系统:
{
"os": [
"darwin",
"linux"
]
}
也可以用非操作符来禁止在某个操作系统上运行:
{
"os": [
"!win32"
]
}
cpu
可以用来指定你的程序运行的cpu:
{
"cpu": [
"x64",
"ia32"
]
}
同样可以用非操作符来禁止在某个cpu上运行,同上。
private
如果设置了private: true,那么npm就不会发布你的包。这是一种防止意外发布私有库的方法。如果要确保给定的包只发布到特定的库中,那么可以使用publishConfig发布时重写配置参数。
publishConfig
这是一组用来发布时使用的配置值。详细配置请看config。
总结
遇到不懂的还是要多看多总结,官方文档是个好东西不要因为全是英文的就不看啊