最近在整理以前写的模块的时候,发现不少模块的package.json写的并非那么规范,因此查阅了一些资料,了解了一下关于如何使用package.json,列出来供你们参考javascript
本文参考了这三篇文章php
这篇文档告诉了你package.json里面,包含了那些字段。这个文件必须是个json文件,而不只是一个js对象。文档中不少属性和设置能够经过npm-config来生成。linux
package.json中有两个字段是必填字段。name字段和version字段。缺乏这两个字段则没法安装npm模块。每一个npm模块也是依赖这两个字段做为惟一标识。若是你的npm模块有所修改,那么对应的version字段也应该有所改变。git
name字段就是你的npm模块的名称。github
name字段须要符合如下规则:express
name必须<= 214 个字节,包括模块的前缀apache
不得以“_” 或者 “.” 做为name的开头
不能有大写字符
由于name字段会成为URL的一部分,或是命令行的一个实参,也有多是个文件夹的名字,因此不能包含no-URL-safe(URL非法)字符。
一些建议:
不要用和node核心模块同样的名称
不要把“js”和”node”字段包含在name中。由于你实际在编写json文件,而包含这些字段会被认为是个js文件而非npm模块,若是你须要指定某些引擎的话,能够在“engines”字段中填写。
name会被写在require()的参数中,因此name最好简短且明确。
建立一个name的时候,最好去https://www.npmjs.com/查查名称是否被占用。
name能够有一些前缀如 例如 @myorg/mypackage.能够在npm-scope的中查看详情。
package.json中有两个字段是必填字段。name字段和version字段。缺乏这两个字段则没法安装npm模块。每一个npm模块也是依赖这两个字段做为惟一标识。若是你的npm模块有所修改,那么对应的version字段也应该有所改变。
version字段必须能够被node-semver这个模块解析,是个和npm捆绑在一块儿的包。
这里有关于版本号形式的含义nodejs中每一个版本形式的含义
一段字符串,用来描述这个npm模块的做用,经过npm search的时候回用到。
一个由字符串组成的数组,也有助于别人经过npm search的时候快速找到你的包。
这个项目的主页URL。 注意:这里和url属性不是一个东西,若是你填了url属性,npm的注册工具会认为你把项目发布到别的地方了,就不会去npm官方仓库去找。
包含你的项目的issue和email地址,若是别人在使用你的包的时候遇到了问题,能够经过这里找到你并提交问题。
它的格式以下:
{ "url" : "https://github.com/owner/project/issues", "email" : "project@hostname.com" }
url和email你能够选填其中一个或者两个,若是只填一个,能够直接写成字符串,而不是一个对象。
若是提供了url, 使用npm bugs命令的时候会用到。
给你的模块定一个协议,让你们知道这个模块的使用权限。例如:遵循BSD-2-Clause or MIT协议。添加一个SPDX许可以下:
{ "license" : "BSD-3-Clause" }
这里查看SPDX协议完整列表。理想状况下,你应该选一个OSI许可(开源许可)。
若是你的模块遵循多种许可,可使用SPDX协议2.0的语法,以下:
{ "license" : "(ISC OR GPL-3.0)" }
若是你使用的是许可证尚未分配一个SPDX标识符,或者若是您使用的是一个定制的许可证,使用这样的字符串值:
{ "license" : "SEE LICENSE IN <filename>" }
而后在模块的顶部include 这个<filename>的文件。
一些旧的模块使用许可对象或一个“许可证”属性,其中包含许可对象数组:
// Not valid metadata { "license" : { "type" : "ISC" , "url" : "http://opensource.org/licenses/ISC" } } // Not valid metadata { "licenses" : [ { "type": "MIT" , "url": "http://www.opensource.org/licenses/mit-license.php" } , { "type": "Apache-2.0" , "url": "http://opensource.org/licenses/apache2.0.php" } ] }
上面的样式如今已经弃用。如今使用SPDX表达式,是这样的:
{ "license": "ISC" } { "license": "(MIT OR Apache-2.0)" }
最后,若是你不但愿别人在任何条件下有任何使用你的包的权限,你能够这样:
{ "license": "UNLICENSED"}
也考虑设置"private": true,来防止模块的意外发布
用户相关的属性:author是一个做者,contributors是一个包含一堆做者的数组。每一个person有一些描述的字段,以下:
{ "name" : "Barney Rubble" , "email" : "b@rubble.com" , "url" : "http://barnyrubble.tumblr.com/" }
也能够用下面的格式简写,npm会自动解析:
"Barney Rubble <b@rubble.com> (http://barnyrubble.tumblr.com/)"
email和url属性实际上都是能够省略的。描述用户信息的还有一个"maintainers"(维护者)属性。
file字段是一个包含在你项目里的文件的数组,里面的内容是文件名或者文件夹名。若是是文件夹,那么里面的文件也会被包含进来,除非你设置了ignore规则。
你也能够在模块根目录下建立一个".npmignore"文件(windows下没法直接建立以"."开头的文件,使用linux命令行工具建立如git bash),写在这个文件里边的文件即使被写在files属性里边也会被排除在外,这个文件的写法".gitignore"相似。
如下文件始终包含在内,不管是否设置:
package.json
README (and its variants)
CHANGELOG (and its variants)
LICENSE / LICENCE
相反,如下文件一般会被忽略:
.git
CVS
.svn
.hg
.lock-wscript
.wafpickle-N
*.swp
.DS_Store
._*
npm-debug.log
main字段规定了程序的主入口文件。若是你的模块命名为foo,用户安装后,就会经过require("foo")来引用该模块,返回的内容就是你的模块的 module.exports指向的对象。
这是一个相对于你的模块文件夹的模块ID,对于大多数的模块,有个主脚本就足够了。
不少模块有一个或多个可执行文件须要配置到PATH路径下。npm就是经过这个特性安装,使得npm可执行。
要用这个功能,给package.json中的bin字段一个命令名到文件位置的map。初始化的时候npm会将他连接到prefix/bin(全局初始化)或者./node_modules/.bin/(本地初始化)。
例如:一个myapp模块多是这样:
{ "bin" : { "myapp" : "./cli.js" } }
因此,当你安装myapp,npm会从cli.js文件建立一个到/usr/local/bin/myapp路径下。
若是你只有一个可执行文件,而且名字和包名同样。那么你能够只用一个字符串,好比:
{ "name": "my-program" , "version": "1.2.5" , "bin": "./path/to/program" }
和下面是同样的效果:
, "version": "1.2.5" , "bin" : { "my-program" : "./path/to/program" } }
用来给Linux下的man命令查找文档地址,是个单一文件或者文件数组。 若是是单一文件,安装完成后,他就是man + <pkgname>的结果,和此文件名无关,例如:
{ "name" : "foo" , "version" : "1.2.3" , "description" : "A packaged foo fooer for fooing foos" , "main" : "foo.js" , "man" : "./man/doc.1" }
经过man foo命令会获得 ./man/doc.1 文件的内容。
若是man文件名称不是以模块名称开头的,安装的时候会给加上模块名称前缀。所以,下面这段配置:
{ "name" : "foo" , "version" : "1.2.3" , "description" : "A packaged foo fooer for fooing foos" , "main" : "foo.js" , "man" : [ "./man/foo.1", "./man/bar.1" ]
会建立一些文件来做为man foo和man foo-bar命令的结果。
man文件必须以数字结尾,或者若是被压缩了,以.gz结尾。数字表示文件将被安装到man的哪一个部分。
{ "name" : "foo" , "version" : "1.2.3" , "description" : "A packaged foo fooer for fooing foos" , "main" : "foo.js" , "man" : [ "./man/foo.1", "./man/foo.2" ] }
会建立 man foo 和 man 2 foo 两条命令。
CommonJs经过directories来制定一些方法来描述模块的结构,看看npm的package.json文件npm's package.json ,会看到有directories标示出doc, lib, and man。
目前这个配置没有任何做用,未来可能会整出一些花样来。
告诉用户模块中lib目录在哪,这个配置目前没有任何做用,可是对使用模块的人来讲是一个颇有用的信息。
若是你在这里指定了bin目录,这个配置下面的文件会被加入到bin路径下,若是你已经在package.json中配置了bin目录,那么这里的配置将不起任何做用。
指定一个目录,目录里边都是man文件,这是一种配置man文件的语法糖。
在这个目录里边放一些markdown文件,可能最终有一天它们会被友好的展示出来(应该是在npm的网站上)
放一些示例脚本,或许某一天会有用 - -!
指定你的代码存放的地方。这个对但愿贡献的人有帮助。若是git仓库在github上,那么npm docs命令能找到你。
以下:
"repository" : { "type" : "git" , "url" : "https://github.com/npm/npm.git" } "repository" : { "type" : "svn" , "url" : "https://v8.googlecode.com/svn/trunk/" }
URL应该是公开的(即使是只读的)能直接被未通过修改的版本控制程序处理的url。不该该是一个html的项目页面。由于它是给计算机看的。
若你的模块放在GitHub, GitHub gist, Bitbucket, or GitLab的仓库里,npm install的时候可使用缩写标记来完成:
"repository": "npm/npm" "repository": "gist:11081aaa281" "repository": "bitbucket:example/repo" "repository": "gitlab:another/repo"
scripts属性是一个对象,里边指定了项目的生命周期个各个环节须要执行的命令。key是生命周期中的事件,value是要执行的命令。
具体的内容有 install start stop 等,详见npm-scripts.
用来设置一些项目不怎么变化,跨版本的项目配置,例如port等。
用法以下:
{ "name" : "foo" , "config" : { "port" : "8080" } }
而后有一个start命令引用npm_package_config_port环境变量,用户也能够用以下方式改写:npm config set foo:port 8001
See npm-config and npm-scripts for more on package configs.
dependencies属性是一个对象,配置模块依赖的模块列表,key是模块名称,value是版本范围,版本范围是一个字符,能够被一个或多个空格分割。
dependencies也能够被指定为一个git地址或者一个压缩包地址。
不要把测试工具或transpilers写到dependencies中。 对比下面的devDependencies。
下面是一些写法,详见https://docs.npmjs.com/misc/s...
version 精确匹配版本
>version 必须大于某个版本
>=version 大于等于
<version 小于
<=versionversion 小于
~version "约等于",具体规则详见semver文档
^version "兼容版本"具体规则详见semver文档
1.2.x 仅一点二点几的版本
http://... 见下面url做为denpendencies的说明
*任何版本
"" 空字符,和*相同
version1 - version2 至关于 >=version1 <=version2.
range1 || range2 范围1和范围2知足任意一个都行
git... 见下面git url做为denpendencies的说明
user/repo See 见下面GitHub仓库的说明
tag 发布的一个特殊的标签,见npm-tag的文档 https://docs.npmjs.com/gettin...
path/path/path 见下面本地模块的说明
下面的写法都是可行的:
{ "dependencies" : { "foo" : "1.0.0 - 2.9999.9999" , "bar" : ">=1.0.2 <2.1.2" , "baz" : ">1.0.2 <=2.3.4" , "boo" : "2.0.1" , "qux" : "<1.0.0 || >=2.3.1 <2.4.5 || >=2.5.2 <3.0.0" , "asd" : "http://asdf.com/asdf.tar.gz" , "til" : "~1.2" , "elf" : "~1.2.3" , "two" : "2.x" , "thr" : "3.3.x" , "lat" : "latest" , "dyl" : "file:../dyl" } }
在版本范围的地方能够写一个url指向一个压缩包,模块安装的时候会把这个压缩包下载下来安装到模块本地。
git URL能够写成这样:
git://github.com/user/project.git#commit-ish git+ssh://user@hostname:project.git#commit-ish git+ssh://user@hostname/project.git#commit-ish git+http://user@hostname/project/blah.git#commit-ish git+https://user@hostname/project/blah.git#commit-ish
commit-ish 能够是任意tag,hash,或者能够检出的分支,默认是master分支。
支持github的 username/modulename 的写法,#后边能够加后缀写明分支hash或标签,以下:
{ "name": "foo", "version": "0.0.0", "dependencies": { "express": "visionmedia/express", "mocha": "visionmedia/mocha#4727d357ea" } }
npm2.0.0版本以上能够提供一个本地路径来安装一个本地的模块,经过npm install xxx --save 来安装,格式以下:
../foo/bar ~/foo/bar ./foo/bar /foo/bar
package.json 生成的相对路径以下:
{ "name": "baz", "dependencies": { "bar": "file:../foo/bar" }
这种属性在离线开发或者测试须要用npm install的状况,又不想本身搞一个npm server的时候有用,可是发布模块到公共仓库时不该该使用这种属性。
若是别人只想使用你的模块,而不须要开发和测试所须要的依赖的时候,这种状况下,能够将开发测试依赖的包,写到devDependencies中。
这些模块会在npm link或者npm install的时候被安装,也能够像其余npm配置同样被管理,详见npm的config文档。
对于一些跨平台的构建任务,例如把CoffeeScript编译成JavaScript,就能够经过在package.json的script属性里边配置prepublish脚原本完成这个任务,而后须要依赖的coffee-script模块就写在devDependencies属性种。
例如:
{ "name": "ethopia-waza", "description": "a delightfully fruity coffee varietal", "version": "1.2.3", "devDependencies": { "coffee-script": "~1.6.3" }, "scripts": { "prepublish": "coffee -o lib/ -c src/waza.coffee" }, "main": "lib/waza.js" }
prepublish脚本会在publishing前运行,这样用户就不用本身去require来编译就能使用。而且在开发模式中(好比本地运行npm install)会运行这个脚本以便更好地测试。
有时,你的项目和所依赖的模块,都会同时依赖另外一个模块,可是所依赖的版本不同。好比,你的项目依赖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字段,就是用来供插件指定其所须要的主工具的版本。
例如:
{ "name": "tea-latte", "version": "1.3.5", "peerDependencies": { "tea": "2.x" } }
上面这个配置确保再npm install的时候tea-latte会和2.x版本的tea一块儿安装,并且它们两个的依赖关系是同级的:
├── tea-latte@1.3.5 └── tea@2.2.0
这个配置的目的是让npm知道,若是要使用此插件模块,请确保安装了兼容版本的宿主模块。
指定发布的时候会被一块儿打包的模块。
若是一个依赖模块能够被使用, 但你也但愿在该模块找不到或没法获取时npm不中断运行,你能够把这个模块依赖放到optionalDependencies配置中。这个配置的写法和dependencies的写法同样,不一样的是这里边写的模块安装失败不会致使npm install失败。
可是须要本身处理模块缺失的状况,例如:
try { var foo = require('foo') var fooVersion = require('foo/package.json').version } catch (er) { foo = null } if ( notGoodFooVersion(fooVersion) ) { foo = null } // .. then later in your program .. if (foo) { foo.doFooThings() }
optionalDependencies 中的配置会覆盖dependencies中同名的配置,最好只在一个地方写。
你能够指定项目的node的版本:
{ "engines" : { "node" : ">=0.10.3 <0.12" } }
和dependencies同样,若是你不指定版本范围或者指定为*,任何版本的node均可以。
也能够指定一些npm版本能够正确的安装你的模块,例如:
{ "engines" : { "npm" : "~1.0.20" } }
记住,除非用户设置engine-strict标记,F不然这个字段只是建议值。
注意:这个属性已经弃用,将在npm 3.0.0 版本干掉。
指定你的模块只能在哪一个操做系统上跑:
"os" : [ "darwin", "linux" ]
也能够指定黑名单而不是白名单:
"os" : [ "!win32" ]
操做系统是由process.platform来判断的,这个属性容许黑白名单同时存在,虽然没啥必要.
若是你的代码只能运行在特定的cpu架构下,你能够指定一个:
"cpu" : [ "x64", "ia32" ]
也能够设置黑名单:
"cpu" : [ "!arm", "!mips" ]
cpu架构经过 process.arch 判断
若是你的模块主要是须要全局安装的命令行程序,就设置它为true,就会提供一个warning,这样来只在局部安装的人会获得这个warning。
它不会真正的防止用户在局部安装,只是防止该模块被错误的使用引发一些问题。
若是这个属性被设置为true,npm将不会发布它。
这是为了防止一个私有模块被无心间发布出去。若是你想让模块被发布到一个特定的npm仓库,如一个内部的仓库,可与在下面的publishConfig中配置仓库参数。
这是一个在publish-time时会用到的配置集合。当你想设置tag、registry或access时特别有用,因此你能够确保一个给定的包没法在没有被打上"latest"标记时就被发布到全局公共的registry。
任何配置均可以被覆盖,固然可能只有"tag", "registry"和"access"和发布意图有关。
参考npm-config来查看那些能够被覆盖的配置项列表。
npm会根据包的内容设置一些默认值。
"scripts": {"start": "node server.js"}
若是模块根目录下有一个server.js文件,那么npm start会默认运行这个文件。
"scripts":{"preinstall": "node-gyp rebuild"}
若是模块根目录下有binding.gyp, npm将默认用node-gyp来编译preinstall的脚本
"contributors": [...]
若模块根目录下有AUTHORS 文件,则npm会按Name (url)格式解析每一行的数据添加到contributors中,能够用#添加行注释
参考资料