package.json参数意义

908 阅读9分钟

name

名字主要是标志包的名字,如果你的包是需要发布的,name和version都是必须的;如果只是自己开发玩玩,这些都是可选的。发布的库想要有前缀,可以参考scope

发布注意:

1. 名字不超过214个字符
2. 不能包含大写字母
3. 不能和发布的库源(如https://www.npmjs.com)中存在同名的

version

如果包需要发布,版本号是必须的,当npm i *安装包时,会安装最新版本,但如果你指定了对应的安装版本,它会安装指定的。版本是通过node-semver解析的

description

描述,它是一个字符串,它在npm 搜索过程中会根据description来搜索,方便查找

keywords

关键字,它是一个数组,同description, 也是在npm搜索过程中方便查找

homepage

项目主页的url

bugs

主要通知相关问题的提交,你可以指定url或email至少一个用来接收通知,如果使用了url,通过npm bugs命令可以被使用

{ 
  "url" : "https://github.com/owner/project/issues", 
  "email" : "project@hostname.com" 
}

license

证书主要用于让他人知道如何使用它,以及有什么样的限制

people fields: author, contributors

作者是一个人,贡献者可以是多人(数组形式)

funding

是一个url组合,主要包含对其它包提供资助帮助的

{ 
    "funding": { 
        "type" : "individual", 
        "url" : "http://example.com/donate" 
    }, 
    "funding": { 
        "type" : "patreon", 
        "url" : "https://www.patreon.com/my-account" 
    }, 
    "funding": "http://example.com/donate",
     "funding": [ { 
        "type" : "individual", 
         "url" : "http://example.com/donate" 
    },
    "http://example.com/donateAlso",
    {
        "type" : "patreon", 
        "url" : "https://www.patreon.com/my-account" 
    } ] 
}

files

files列举你的包安装依赖需要包含的文件,它的文件规则同.gitignore文件相反,省略该字段将使其默认为 ["*"],这意味着它将包括所有文件

main

main作为模块id,它是程序的主入口。如果没有设置,默认是根目录下的index.js文件

browser

它主要告诉用户,这里面涉及到nodeJS的语法,如果打算在浏览器上使用,建议用browser来定义入口,而非使用main,非浏览器的的默认使用main。

image.png

module

module它不是package.json的官方文档字段,主要用于es module引入方式,现在一般采用type: "module"形式

bin

许多包都有一个或多个可执行文件,全局安装安装到系统path目录,然后通过bin下面的名字就能访问

{ "bin": 
    { "myapp": 
        "./cli.js" 
    } 
 }

当我们安装myapp, 像mac它将创建从cli.js 到/usr/local/bin/myapp 的符号链接,window系统是到C:\Users{Username}\AppData\Roaming\npm\myapp.cmd 如果它只是一个可执行文件,可以将它作为字符串提供

{ 
    "name": "my-program", 
    "version": "1.2.5", 
    "bin": "./path/to/program" 
}

上面等同于下面这段代码

{ 
    "name": "my-program", 
    "version": "1.2.5",
    "bin": { 
        "my-program": "./path/to/program" 
     } 
}

请确保你的文件在bin中以#!/usr/bin/env node开头,否则脚本将没有node可执行文件下启动

man

指定单个或数组形式的文件供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/doc.1文件使其目标对应 man foo,如果文件不以包名开始,它就有前缀

{
    "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的哪里

image.png

{
    "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

directories

CommonJS Packages 规范详细介绍了通过使用directories对象指示包结构,如果你看 npm's package.json,你将看到directories有doc、lib、man目录。

image.png

directories.bin

repository

指定代码所在的地方,对于想要贡献代码的有帮助。如果你的git仓库在github上,执行npm docs可以找到你

 
{
  "repository": {
    "type": "git",
    "url": "https://github.com/npm/cli.git"
  }
}

对于GitHub, GitHub gist, Bitbucket或者GitLab仓库,你可以使用和npm install相同的快捷语法

 
{
  "repository": "npm/npm",
  "repository": "github:user/repo",
  "repository": "gist:11081aaa281",
  "repository": "bitbucket:user/repo",
  "repository": "gitlab:user/repo"
}

如果你的包package.json不在根目录(例如monorepo多仓库管理),你可以指定特定的目录

 
{
  "repository": {
    "type": "git",
    "url": "https://github.com/facebook/react.git",
    "directory": "packages/react-dom"
  }
}

scripts

“scripts”属性是包含各种执行指令,key标识的是事件,value表示的运行起点。

config

“config”对象可以配置一系列参数,可用于脚本持续升级

 
{
  "name": "foo",
  "config": {
    "port": "8080"
  }
}

dependencies

依赖关系是一个简单对象,包含包名到版本范围的映射关系,版本范围是一个字符串,通过‘.’来分割描述

请不要将测试工具、转换器或其它开发工具放在dependencies对象中,见下面的 devDependencies

看 semver 有很多信息关于版本范围的描述.

  • version 必须准确匹配版本 version
  • >version版本必须大于 version
  • >=version 版本必须大于等于
  • <version 版本小于
  • <=version 版本小于等于
  • ~version "约等于版本" 详细看 semver,如果写入的是0.13.0\color{gray}{~0.13.0} ,则当运行npm update时,会更新补丁版本,即0.13.1\color{gray}{~0.13.1} 可以,但0.14.0\color{gray}{~0.14.0} 不可以
  • ^version "兼容版本" 详细 semver,只会执行不更改最左边非零数字的更新,如果写入的是0.13.0\color{gray}{^0.13.0} ,则当运行npm update时,可以更新到0.13.1\color{gray}{^0.13.1} 0.13.2\color{gray}{^0.13.2} 等,但不能更新到0.14.0\color{gray}{0.14.0} 或更高版本。如果写入的是1.13.0\color{gray}{^1.13.0} ,则当运行npm update时,可以更新到1.13.1\color{gray}{1.13.1} 1.14.0\color{gray}{1.14.0} 等,但不能更新到2.0.0\color{gray}{2.0.0} 或更高版本
  • 1.2.x 1.2.0, 1.2.1, 等.,当不包含 1.3.0
  • http://... 见下面的 'URLs as Dependencies'
  • *匹配所有版本
  • "" 只是空字符串,类似*
  • version1 - version2 等同于大于等于version1且小于等于version2.
  • range1 || range2 小于range1或者大于rang2都可以.
  • git... 见下面的 'Git URLs as Dependencies'
  • user/repo 见下面的 'GitHub URLs'
  • tag 指定tag版本,并发布带tag的版本,见 npm dist-tag
  • path/path/path 见Local Paths

如下所示

 
{
  "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"
  }
}

URLs as Dependencies

你可以指定一个tarball url来替代范围包,这个tarball包在你安装的同时会下载到本地

Git URLs as Dependencies

Git urls 的格式如下:

 
<protocol>://[<user>[:<password>]@]<hostname>[:<port>][:][/]<path>[#<commit-ish> | #semver:<semver>]

<protocol> 是 gitgit+sshgit+httpgit+https, or git+file中的一个.如果提供了#<commit-ish>,它将准确的克隆并提交;如果commit-ish的格式是 #semver:<semver><semver> 可以是任何有效的semver范围或确切版本,npm将在远程仓库中查找与它匹配的任何标签和引用,像查找注册表一样。如果 #<commit-ish>#semver:<semver> 都没使用,使用默认分支。

例如:

 
git+ssh://git@github.com:npm/cli.git#v1.0.27
git+ssh://git@github.com:npm/cli#semver:^5.0
git+https://isaacs@github.com/npm/cli.git
git://github.com/npm/cli.git#v1.0.27

当安装git仓库,package.json中存在的字段将认定它是需要执行构建的,因此你的仓库会被克隆到一个临时目录下,所有的deps将安装,相关脚本执行并将结果打包安装

如果你的git 依赖使用workspaces,如下流程将会执行:

  • build
  • prepare
  • prepack
  • preinstall
  • install
  • postinstall

如果你的git 仓库包含pre-built(预构建)工作,你需要确保以上执行脚本没有被定义,你的依赖在每次安装时将重新构建

GitHub URLs

版本是 1.1.65, 你可以将GitHub urls设置 "foo": "user/foo-project". 和git URLs一样,可以包含commit-ish后缀, 例如:

 
{
  "name": "foo",
  "version": "0.0.0",
  "dependencies": {
    "express": "expressjs/express",
    "mocha": "mochajs/mocha#4727d357ea",
    "module": "user/repo#feature/branch"
  }
}

Local Paths

版本2.0.0 ,你可以提供本地目录作为路径来包含包。本地路径保存安装方式使用 npm install -S 或者 npm install --save, 使用格式如下:

 
../foo/bar
~/foo/bar
./foo/bar
/foo/bar

在这种情况,它们作为相对路径将添加到package.json, 例如:

 
{
  "name": "baz",
  "dependencies": {
    "bar": "file:../foo/bar"
  }
}

这特征比较适用于本地离线开发或者不想访问外部服务器来安装测试,但是它不能被使用在公共仓库的发布包。

note:这种情况下直接执行npm install,通过本地路径安装的包不会有它自己的依赖项。必须在它本地路径下执行 npm install.

devDependencies

如果有人想在自己程序中下载或使用你的模块,他们可能不想也不需要下载和构建你使用的测试和文档框架,这种情况最好将附加项映射到devDependencies。当使用npm link 或者npm install 从你根目录进行安装时,它可以像其它npm配置config参数进行管理。

对于不确定平台的构建步骤,像编译CoffeeScript或其它语言为JavaScript,使用 prepare 脚本执行,并将所有需要包设置devDependency,例如:

 
{
  "name": "ethopia-waza",
  "description": "a delightfully fruity coffee varietal",
  "version": "1.2.3",
  "devDependencies": {
    "coffee-script": "~1.6.3"
  },
  "scripts": {
    "prepare": "coffee -o lib/ -c src/waza.coffee"
  },
  "main": "lib/waza.js"
}

prepare脚本运行在发布之前,所以用户使用它的功能而不需要引用编译他们,在开发模式执行这个脚本,便于测试。我理解的devDependencies主要是一些本地需要线上不需要的包,像一些babel、eslint等插件,对比上面的dependencies

peerDependencies

有些情况下,你想要你的宿主工具、包和库的兼容性,而不一定对主机执行require,这通常称为“插件”,你的模块可能会暴露特定的接口,这是主机文档所期望的。例如:

 
{
  "name": "tea-latte",
  "version": "1.3.5",
  "peerDependencies": {
    "tea": "2.x"
  }
}

这能确保你的包tea-latte在安装的时候会“跟随”安装依赖的第二个主要的包tea ,你通过执行npm install tea-latte,发现它的依赖关系图如下:

 
├── tea-latte@1.3.5
└── tea@2.2.0

在npm版本3-6,peerDependencies都不是自动安装,会给出警告提示,在npm v7默认自动安装。如果无法正确解析树,它将安装其它具有冲突的插件,这样就会引起错误。因此你需要确保你需要的插件被广泛使用,不是特定锁定指定版本。如果你主机包是 1.x版本,建议使用"^1.0" 和 "1.x"。我理解的peerDependencies是安装主包的时候需要依赖其它的包,这其它的包写在peerDependencies映射里。

peerDependenciesMeta

当你安装包时,如果在peerDependencies 中的依赖没被安装,npm将会发出警告。peerDependenciesMeta 字段用于向npm提供更多信息关于peer dependencies被使用,它可以将peer dependencies标记为可选,例如:

 
{
  "name": "tea-latte",
  "version": "1.3.5",
  "peerDependencies": {
    "tea": "2.x",
    "soy-milk": "1.2"
  },
  "peerDependenciesMeta": {
    "soy-milk": {
      "optional": true
    }
  }
}

将peer dependency标记可选后,如果soy-milk没有安装,npm也不会发出警告,这允许你集成和与主机包交互,但没必要安装所有主机包.

bundleDependencies

它定义了一组包名称,这个在发布的时候捆绑在一起。如果你需要保存npm包或单文件下载,你可以在bundleDependencies中指定包名,并执行 npm pack,如:

 
{
  "name": "awesome-web-framework",
  "version": "1.0.0",
  "bundleDependencies": [
    "renderized",
    "super-streams"
  ]
}

我们可以通过执行npm pack获得 awesome-web-framework-1.0.0.tgz 文件,我们在新项目中执行npm install awesome-web-framework-1.0.0.tgz,这个文件包含renderizedsuper-streams的依赖,注意包名称不包含任何版本,因为它在dependencies指定。

optionalDependencies

如果npm没被发现或安装失败,你可以将包映射放到optionalDependencies中,它构建失败不会导致安装失败,执行npm install --omit=optional\ 将阻止依赖被安装。如果你的程序缺乏依赖:

 
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包,因此最好将它写在同一个地方。

engines

如果你指定node运行版本:

 
{
  "engines": {
    "node": ">=0.10.3 <15"
  }
}

os

如果你指定特定的操作系统上运行:

 
{
  "os": [
    "darwin",
    "linux"
  ]
}

你也可以通过取反'!'的方式阻止:

 
{
  "os": [
    "!win32"
  ]
}

cpu

如果你的代码仅在指定的cpu架构上运行,可以指定如下:

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

 os 也是一样:

 
{
  "cpu": [
    "!arm",
    "!mips"
  ]
}

private

如果你在package.json中设置"private": true ,你的npm包将拒绝发布。这是防止意外发布私有仓库的方法。

workspaces

workspaces通过数组文件来描述本地系统包含的文件,如下例子中,所有的文件 ./packages都可以当作工作区,只要它们包含有效的package.json文件:

 
{
  "name": "workspace-example",
  "workspaces": [
    "./packages/*"
  ]
}

DEFAULT VALUES

npm根据包内容会有一些默认值。

  • "scripts": {"start": "node server.js"}

    如果有一个server.js 文件在你包的根目录,npm将默认start 命令来执行node server.js

  • "scripts":{"install": "node-gyp rebuild"}

    如果有一个binding.gyp文件在你包的根目录,你不需要定义install 和preinstall 脚本,npm 默认install命令执行node-gyp

参考文档

  1. package.json官方文档
  2. main field
  3. browser/module/main