logo

npm 全称:Node Package Manager (Node 包管理器),目前是Web前端开发重要依赖工具之一。安装Node.js默认会安装npm,前端各种资源都可以通过一个npm命令下载到自己的本地计算机上。

用户通过一个命令将npm上发布的包下载自己本地计算机并在项目中使用,也可以将自己的包发布到npm上供全球Web前端开发者下载使用。

npm的出现极大提升了前端开发体验。

npm 命令

npm help

1
npm help <command>

通过该命令可以帮助我们快速查看具体npm命令的用途。

npm help -l可以查看所有所有npm命令

npm init

npm包必须有个 package.json文件,通过npm init可以让自动在目录下创建一个package.json文件,命令行会弹出几个问题用于填充package.json。如果你想快速跳过可以使用npm init -y命令。

npm install

npm install用于将依赖的包下载到本地node_modules目录中

npm install <package name>可以是注册在npm服务上的包,也可以是Github上一个具体项目地址。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ npm install express 
$ npm install git@github.com:expressjs/express.git

npm install (with no args, in package dir)
npm install [<@scope>/]<name>
npm install [<@scope>/]<name>@<tag>
npm install [<@scope>/]<name>@<version>
npm install [<@scope>/]<name>@<version range>
npm install <git-host>:<git-user>/<repo-name>
npm install <git repo url>
npm install <tarball file>
npm install <tarball url>
npm install <folder>

npm安装的包会记录在package.json文件中。

package.json文件有两种记录安装包的方式:生产依赖(dependencies)和开发依赖(devDependencies)。

1
2
3
"dependencies": {
"express": "^4.0.0"
}
1
2
3
"devDependencies": {
"express": "^4.0.0"
}

npm install <packagename>安装默认是生产依赖,也可以使用npm install -save <packagename>npm install -S <packagename>

开发依赖的安装命令是:npm install -save-dev <packagename>npm install -D <packagename>

npm ci

npm ci功能和npm install命令作用一样,它比npm install安装更快,因为它会跳过一些面向用户的操作,它的安装比npm install更严格,它可以帮助捕获由大多数npm用户的增量安装的本地环境引起的错误或不一致。

npm cinpm install区别有:

  1. 安装前目录必须存在package-lock.jsonnpm-shrinkwrap.json
  2. 如果package-lock.json包中锁定的包版本和package.json中包版本不一致,则npm ci将提示错误并提示错误。
  3. npm ci只能整项目依赖包的安装,不能安装单个依赖包。
  4. 如果node_modules目录存在,在npm ci安装前会移除node_modules目录。
  5. 它不会对package.json和任何锁定包版本的文件进行操作。

npm ci一般在自动话环境中使用,例如:测试平台,持续化集成,部署。

npm update

npm update用于更新本地依赖包。它会先查询远程服务器最新包的版本,再与本地版本进行比较,如果远程版本更新并符合本地版本安装规,它就将本地依赖包更新到最新版本。

npm update更新时,添加参数-S-D。它会将package.json中的版本号更新。

npm dist-tag

npm dist-tag是管理包标签指令

1
2
3
$ npm dist-tag add <pkg>@<version> [<tag>]
$ npm dist-tag rm <pkg> <tag>
$ npm dist-tag ls [<pkg>]
  • add:使用给指定的包版本设定标签
  • rm:将包中不需要的标签移除
  • ls:将包的所有标签展示出来

在安装包时,可以通过设定标签名称下载指定版本的包

1
$ npm install <name>@<tag>

npm config

npm config命令用于管理npm包管理文件

1
2
3
4
5
6
7
$ npm config set <key> <value> [-g|--global]
$ npm config get <key>
$ npm config delete <key>
$ npm config list [-l] [--json]
$ npm config edit
$ npm get <key>
$ npm set <key> <value> [-g|--global]

用的最多的npm config命令是npm config set registry https://registry.npm.taobao.org

npm version

你还在手动更新package.json中的版本号嘛?现在一个npm version xxx命令就可以搞定了。它会将你设置的版本号写入package.json文件中。

npm包版本号的规则是:重大版本号.功能版本号.修复优化版本号

npm outdated

此命令将检查注册表,查看是否有安装的包已过时

1
2
3
4
5
6
7
  npm outdated [[<@scope>/]<pkg> ...]
Package Current Wanted Latest Location
glob 5.0.15 5.0.15 6.0.1 test-outdated-output
nothingness 0.0.3 git git test-outdated-output
npm 3.5.1 3.5.2 3.5.1 test-outdated-output
local-dev 0.0.3 linked linked test-outdated-output
once 1.3.2 1.3.3 1.3.3 test-outdated-output

如果不指定pkg,则检查所有过期的包;若指定pkg,则检查指定的pkg。\

  • wanted 显示符合semver规范的最大版本号。若没有多余版本号,则显示当前版本。
  • latest 显示注册表中被标记为latest的版本。默认情况下latest标记表示最新版本,特殊情况下不是,这取决于开发人员的包管理制度。
  • location 显示包在依赖关系树中的位置。请注意,npm outdated默认depth为0,仅看到过期包的顶级依赖项。
  • package 显示包名。若使用了(–long/-l)则还是显示这个包属于dependencies还是devDependency。
1
npm outdated --depth=1 // 显示依赖关系树最大深度,默认是 0

npm ls

用于查询工程或全局已安装的npm包依赖树。
可以设定 包名查看 安装情况。

1
2
3
npm ls [[<@scope>/]<pkg> ...]

aliases: list, la, ll

可以通过--depth n指定层级

npm view

打印指定包的信息.

1
2
3
npm view [<@scope>/]<name>[@<version>] [<field>[.<subfield>]...]

aliases: info, show, v

package.json

每个npm包根目录下都会有一个package.json文件,该文件含有包的所有重要信息,例如:包名,版本号,许可协议等。

name

name表示该项目的名称,它的命名规则是限制的:

  • 名称长度必须小于214个字节
  • 不能以._下划线开头
  • 不能包含大些字母
  • name会成为URL的一部分,所以不能包含非法的URL字符

npm官方给了一些命名的建议:

  • 不要使用和node.js模块相同的名称
  • 名称中主要包含jsnode字符串
  • 名称也许会被写入require参数中,所以最好取个简单有意义的名称
  • 创建一个名称前先到https://www.npmjs.com/查询下该名称是否已经被使用

version

如果你计划发布你的npm包,你必须要确保在package.json文件中定义了nameversion字段。

namepackage字段是包的唯一性标志,包的区分就是依靠namepackage字段。

version字段定义当前包的版本号,版本号的命名规则是:重大版本号.功能版本号.修复优化版本号

发布稳定版本

1
2
3
4
5
6
7
# 更新版本号(major | minor | patch | premajor | preminor | prepatch | prerelease)
# 大版本并且不向下兼容时,使用 major
# 有新功能且向下兼容时,使用 minor
# 修复一些问题、优化等,使用 patch
# 下面比如更新一个 patch 小版本号
$ npm version patch
$ npm publish

预发布版本

1
2
3
4
5
6
7
# 发布一个 prelease 版本,tag=beta
$ npm version prerelease
$ npm publish --tag beta

# 增加预版本号前缀alpha
$ npm version prerelease --preid=alpha
v1.0.0-alpha.0

description

description字段描述包的一些信息,可以方便用户通过npm search搜索到你的npm

homepage

homepage字段声明包的主页地址

license

license字段定义你的包使用的许可证,不同的许可证定义了你的包使用范围和用途。https://spdx.org/licenses/可以看到所有许可证和它的详细说明

main

main定义了包入口的文件,通过require()引入你的包时,包管理器会将main中定义的文件引入进去。main默认入口文件名是index.js

dependencies

dependencies字段用于定义项目运行所依赖的库。它定义为一个对象,key表示包名称,value是包的版本号。

依赖包的版本号定义有四种形式:

  • 指定固定的版本:1.2.0
  • 波浪号+指定版本号:~1.2.0它表示安装1.2.x最新的版本,不低于1.2.0,但不安装1.3.0。安装时不改变大版本号和次要版本号
  • 插入号+指定版本包: ^1.2.0,它表示安装1.x.x最新的版本,不安装2.x.x版本,也就是不改变大版本号。但是如果大版本号是0,则它的意义和波浪号一样,它不改变次版本号。因为大版本号是0说明该包还只是测试简单。
  • latest: 安装最新的版本

devDependencies

devDependencies字段定义开发是依赖的包,它表示项目运行时并不依赖的包。

peerDependencies

1
如果你安装我,那么你最好也安装X,Y和Z.

有时候做一些插件开发,比如grunt等工具的插件,它们往往是在grunt的某个版本的基础上开发的,而在他们的代码中并不会出现require(“grunt”)这样的依赖,dependencies配置里边也不会写上grunt的依赖,为了说明此模块只能作为插件跑在宿主的某个版本范围下,可以配置peerDependencies:

1
2
3
4
5
6
7
{
"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知道,如果要使用此插件模块,请确保在宿主环境按照了我需要的依赖包(peerDependencies中声明的包)。
即使宿主环境并没有使用该依赖包,但还是会在它的node_modules中按照该依赖包.

npm2和npm3中peerDependencies的区别

正如上一节谈论的,在npm2中,PackageA包中peerDependencies所指定的依赖会随着npm install PackageA一起被强制安装,所以不需要在宿主环境的package.json文件中指定对PackageA中peerDependencies内容的依赖。

但是在npm3中,peerDependencies的表现与npm2不同:

npm3中不会再要求peerDependencies所指定的依赖包被强制安装,相反npm3会在安装结束后检查本次安装是否正确,如果不正确会给用户打印警告提示。

就拿上面的例子来说,如果我们npm install PackageA安装PackageA时,你会得到一个警告提示说:

PackageB是一个需要的依赖,但是没有被安装。
这时,你需要手动的在MyProject项目的package.json文件指定PackageB的依赖。

另外,在npm3的项目中,可能存在一个问题就是你所依赖的一个package包更新了它peerDependencies的版本,那么你可能也需要在项目的package.json文件中手动更新到正确的版本。

bundledDependencies

上面的单词少个d,写成bundleDependencies也可以。
指定发布的时候会被一起打包的模块。

optionalDependencies

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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中的配置,最好只在一个地方写。

config

用来设置一些项目不怎么变化的项目配置,例如port等。
用户用的时候可以使用如下用法:

1
http.createServer(...).listen(process.env.npm_package_config_port)

可以通过npm config set foo:port 80来修改config

1
2
3
4
{ 
"name" : "foo",
"config" : { "port" : "8080" }
}

npx

npx用于执行npm包的二进制脚本。

npx <command>它会查找node_modules/.bin目录对于的可执行二进制脚本。如果本地没有对于的可执行二进制脚本,它会去全局查找。如果全局也没有,它就会从远程仓库下载对应的npm包。

1
2
$ npm i -D webpack
$ npx webpack -v

npm5.2.0版本之后会默认安装npx包。

有了npx,对于需要执行的npm包二进制命令,你不用将它写进scripts或进行全局安装。

发布npm包

将包发布到npm远程仓库非常简单,只需要三个步骤(确保你的包准备好了)。

  1. npm adduser注册一个npmjs.com的账号
  2. npm login登录已有的账号
  3. npm publish发布包(在包的根目录执行)

注意: 在发布前,你应该登录https://www.npmjs.com 看下自己的包名是否已经存在。

​ 如果你的registry指向其它镜像,你需要将它设定为https://registry.npmjs.com/

一个完整的npm包,应该包括:

  • package.json文件
  • README.md文件,说明包的用途和使用方式
  • index.js文件,包的入口文件
  • tests目录,单元测试文件目录