Skip to main content

npm

npm (Node Packaged Modules) is node's official package manager. You can also see all the versions of node and corresponding npm here.

Overview

npm CLI documentation

Atnz2F

Acronym

-g

--global 缩写为 -g,表示安装之后的包将位于系统预设的全局目录之下。

-S

--save 缩写为 -S,表示安装的包将写入 package.json 里面的 dependencies

-D

--save-dev 缩写为 -D,表示将安装的包将写入 packege.json 里面的 devDependencies

-E

--save-exact 缩写为 -E,表示安装的包的版本是精确指定的。比如 npm install react -Edependencies 中 react 版本为:

"react": "16.13.1"

以下缩写则不是很常用,仅供参考:

-O

--save-optional 缩写为 -O,表示将安装的包将写入 packege.json 里面的 optionalDependencies

-B

--save-bundle 缩写为 -B,表示将安装的包将写入 packege.json 里面的 bundleDependencies

npm outdated

例如在 node 项目中运行 npm outdated 命令,如下图所示:

0zEWlT

wanted 就是 dependenciesdevDependencies 字段中指定的版本号应当升级的版本,可以看出上面列表 less 用的是 ^,所以 wanted 会提示更新次要版本号。

npm install

Install package

这个是 npm 中最常用的命令:

npm install packageName
tip

可以简写为:

npm i packageName

这个命令会将 package 安装在当前目录下 node_modules 目录内,可执行命令(如果有)安装在 node_modules/.bin 目录下。全局安装使用 -g 选项:

npm install -g packageName  # npm i -g packageName
tip

具体安装在 usr 还是 ~ 下面,还需要看 node/npm 的安装方式,推荐将 node 安装在 ~ 下面,可以使用 nvm 和 n 来安装 node。

如果想指定具体的安装位置,可以使用以下方法:

  • 在命令中添加 --prefix 标记 (e.g. npm i -g packageName --prefix ~/.node_modules )。
  • 使用 npm_config_prefix 环境变量。
  • 使用用户配置文件 ~/.npmrc

第一个方法已不被推荐因为你需要记住位置并且每次操作都需要添加参数。第二个方法只是添加下列行到你的 shell 配置文件 (e.g. .bash_profile, .zshrc)。

PATH="$HOME/.node_modules/bin:$PATH"
export npm_config_prefix=~/.node_modules

不要忘记source一下 shell 配置文件。

第三个方法你可以使用命令:

npm config edit

你可以找到 prefix 选项并且设置一个期望的位置:

prefix=~/.node_modules

不要忘记删除行前面的; 否则会被当作注释。你现在可以添加可执行命令的位置到你的 shell 配置文件。

export PATH="$HOME/.node_modules/bin:$PATH"

同样,也不要忘记source一下 shell 配置文件。

Install local package

在 npm@5 之前的版本,如果将本地目录作为依赖来安装,将会把文件目录作为副本拷贝到 node_modules 中。而在 npm@5 中,将改为使用创建 symlinks 的方式来实现(使用本地 tarball 包除外),而不再执行文件拷贝。这将会提升安装速度:

npm install ../packages/mylib
npm install file://packages/mylib

有关新的 file:// 规范描述可以参考官方的 file-specifiers

Update package

除了安装包,npm i 也可以用于升级包,比如 npm i packageName 将会把 node_modules 中相应的包升级到 wanted 版本,同时也会自动更新 package.jsonpackage-lock.json

caution

npm inpm i packageName 的行为是不一样的,npm i 会优先去 lockfile 里面找对应的版本,即使有 wanted 的更新版本也不会去下载安装,除非没有 lockfile。

npm --prefix [path][command]

To run an npm script from another directory, use --prefix, similar to "yarn --cwd"

npm --prefix ./client install

npm ci

该命令类似于 npm i ,但它旨在用于自动化环境,如测试平台,持续集成和部署。

优点:

  • 通过跳过某些面向用户的功能,它可以比 npm i 快得多。
  • 可以避免 npm i 增量安装而引起的本地和线上不一致等问题。

例如配置 Travis 以使用 npm ci 而不是 npm i:

# .travis.yml
install:
- npm ci
# keep the npm cache around to speed up installs
cache:
directories:
- '$HOME/.npm'

总之,使用 npm i 和使用的主要区别 npm ci 是:

  • 使用 npm ci 时该项目必须有一个 package-lock.jsonnpm-shrinkwrap.json
  • npm ci 永远不会写入 package.json 或任何 lockfile,安装基本上是冻结的。
  • 如果 lockfile 中的依赖项与其中的依赖项不匹配 package.jsonnpm ci 则将退出并显示错误,而不是更新 lockfile。
  • 如果 node_modules 已经存在,它将在 npm ci 开始安装之前自动删除。
  • npm ci 只能一次安装整个项目,使用此命令无法添加单个依赖包。
tip

yarn 没有这个命令,但有一个比较类似的命令:yarn install --frozen-lockfile

npm update

更新包有两种方式 npm i packageName<@version> 或者 npm update packageName

tip

可以简写为:

npm up packageName
caution
  • npm i 的方式不加版本号和 up 的效果是一样的,只更新到 wanted 版本,有新版的改动都会更新 package.json 和 lock 文件。
  • npm i 可以加版本号更新到最新版,比如^2.3.0更新到最新版^3.0.0之后,package.json 和 lock 文件都会更新,且以插入号的方式来更新 package.json 文件。但是 up 命令无论加不加版本号它只会更新到 wanted 版本。

关于 up 命令方面的基础知识

npm update packageName # alias up

对于全局环境安装的包 ( -g )

npm up -g packageName

更新单个全局包,比如yarn

npm up -g yarn
tip

全局安装的包可能需要管理员权限,取决于 node 的安装目录是否是 ~

更新所有包有时你只希望更新所有包,去掉包名将试图更新所有包。

npm up

或者添加 -g 标记更新全局环境安装的包

npm up -g

npm uninstall

删除使用 -g 标记安装的包只须:

npm uninstall packageName
tip

可以简写为:

npm un packageName
# or
npm r packageName

对于全局安装的包 加上 -g 即可:

npm r -g packageName
tip

全局安装的包可能需要管理员权限,取决于 node 的安装目录是否是 ~

npm list

若要显示已安装的包的树形视图执行:

npm list -g
tip

可以简写为:

npm ls packageName
# or
npm ll packageName
# or
npm la packageName

若只要显示第一层结构的包(你自己安装的包),可以执行:

npm ls -g --depth=0

npm cache

npm installnpm update命令,从 registry 下载压缩包之后,都存放在本地的缓存目录。

npm config get cache

npm 的缓存目录是通过 cache 变量指定的,一般默认是在~/.npm 文件夹,可以执行下面的命令查看

npm config get cache

在 npm@5 以前,每个缓存的模块在 ~/.npm 文件夹中以模块名的形式直接存储,例如 koa 模块存储在~/.npm/koa 文件夹中。而 npm@5 版本开始,数据存储在 ~/.npm/_cacache 中,并且不是以模块名直接存放。

caution

npm@5 版本开始,数据存储在 ~/.npm/_cacache 中,并且不是以模块名直接存放。

npm cache add

npm cache 提供了三个命令,分别是npm cache add, npm cache clean, npm cache verify

npm cache add

官方解释说这个命令主要是 npm 内部使用,但是也可以用来手动给一个指定的 package 添加缓存。

This command is primarily intended to be used internally by npm, but it can provide a way to add data to the local installation cache explicitly.

npm cache clean --force

npm cache clean --force

删除缓存目录下的所有数据。npm@5 重写了整个缓存系统,缓存将由 npm 来全局维护不用用户操心,这点也是在向 yarn 看齐。升级新版后,用户基本没有手动操作 npm cache 的场景。npm cache clean 将必须带上 --force 参数才能执行,并且会收到警告。

npm 的缓存是使用 pacote 模块进行下载和管理,基于 cacache 缓存存储。由于 npm 会维护缓存数据的完整性,一旦数据发生错误,就回重新获取。因此不推荐手动清理缓存,除非需要释放磁盘空间,这也是要强制加上--force 参数的原因。

npm cache verify

验证缓存数据的有效性和完整性,清理垃圾数据。

npm cache verify

offline/online

npm 提供了离线安装模式,使用 --offline, --prefer-offline, --prefer-online 可以指定离线模式。

--prefer-offline / --prefer-online

离线优先/网络优先模式。

  • 如果设置为 --prefer-offline 则优先使用缓存数据,如果没有匹配的缓存数据,则从远程仓库下载。
  • 如果设置为 --prefer-online 则优先使用网络数据,忽略缓存数据,这种模式可以及时获取最新的模块。

--offline

完全离线模式,安装过程不需要网络,直接使用匹配的缓存数据,一旦缓存数据不存在,则安装失败。

npm config

npm config set <key> <value>
npm config get [<key>]
npm config delete <key>
npm config list [--json]
npm config edit
npm set <key> <value>
npm get [<key>]

比如更换仓库:

npm config set registry https://registry.npmjs.org/

便于记忆可以用 edit 命令再进行编辑:

npm config edit

https://docs.npmjs.com/cli/link

同一个目录下:

cd path/my-project
npm link path/npm-package

不同目录下:

# 先到模块目录,把它 link 到全局
cd path/npm-package
npm link

# 再去项目目录通过包名来 link
cd path/my-project
npm link npm-package

去掉 link:

npm unlink npm-package
caution
  • 如果在 my-project 里面重新执行过 npm i 那么 link 就会失效,需要重新 link。
  • 在 npm-package 里面的修改能自动同步到 my-project。
  • 使用 nvm 的时候要注意不同项目是否用的是同一个版本的 node,否则 link 是不会生效的。

npx

  • 安装

如果 npm 的版本 >=5.2.0 应该会自带 npx 命令,直接使用即可。如果没有则 npm install -g npx。完整的命令使用说明,运行npx即可

  • 机制
  1. 首先会自动检查当前项目中的可执行依赖文件(即./node_modules/.bin下面的可用依赖)
  2. 如果不存在就会去环境变量 path 中寻找
  3. 如果还没有就会自动安装,其安装的依赖位于~/.npm/_npx之中(_macOS@10.14, npm@6.3.0_npm config get cache可查看_npx所在目录),安装的依赖只是临时的。

比如运行了 npx http-server 会在该目录下面生成 24745,当服务停掉时,该目录会自动删除。

ftmFX1

PS: 具体能临时存放多久,待补充。

  • 本地二进制的简写方式

一般情况下,如果你想执行一个本地项目安装的二进制文件而不是全局安装的,你需要这样:

./node_modules/.bin/jest

有了 npx 之后可以 简写如下形式:

$ npx jest
  • 不用下载直接使用的 npm 包命令

使用 npx create-react-app my-app 来执行 create-react-app 命令时,它会正常地帮我们创建 React 应用而不会实际安装 create-react-app。

也可以快速开启一个静态服务器:

$ npx serve
┌─────────────────────────────────────────────────┐
│ │
│ Serving!
│ │
│ - Local: http://localhost:5000 │
│ - On Your Network: http://172.20.10.8:5000 │
│ │
│ Copied local address to clipboard!
│ │
└─────────────────────────────────────────────────┘

这将可以简化一次性命令的包,比如 xxx-init 来初始化项目,直接 npx xxx-init 即可。

  • 直接运行来自于 Gist 的脚本
$ npx https://gist.github.com/zkat/4bc19503fe9e9309e2bfaa2c58074d32
npx: 1 安装成功,用时 9.985
yay gist
  • 测试不同的 npm 包版本

查询最新的 uglify-js 的版本:

$ npx uglify-js --version
uglify-js 3.4.9

现在我们想获得最新的 2.x 版本的 uglify-js:

$ npx uglify-js@2 --version
uglify-js 2.8.29

所以我们就可以很轻松的使用不同版本的 uglify-js 来压缩代码了:

npx uglify-js@2.8.29 main.js -o ./dist/main.js

更多阅读:

.npmrc

Why we need

常用场景:前端项目开发离不开安装各种 npm 依赖包,可以选择 npm 官方仓库也可以私有仓库,但更改仓库地址需要在安装时控制台打命令,比较麻烦,而 .npmrc 可以很方便地解决上面问题。当安装项目的依赖包时,会优先查找并读取项目根目录下的.npmrc 文件的配置。

How to use

npmrc 使用起来非常的方便。只需要如下几个步骤:

  1. 在项目根目录创建一个.npmrc 的文件
  2. 在这个文件中写入相关配置信息

Configuration

registry=https://registry.npmjs.org

定义仓库地址,进入该工程目录下,npm registry 会自动以该配置为准,不需要手动执行 npm config set registry https://registry.npmjs.org

save-exact=true

例如配置该项之后执行 npm install lodash 会产生如下效果:

{
"dependencies": {
"lodash": "3.10.1"
}
}

engine-strict=true

执行 npm install 的时候会检查是否满足 package.json 中"engines"定义的 node 和 npm 的版本。

但要注意的是如果开启了此项,也会检查依赖包的 package.json 中"engines"定义的 node 和 npm 的版本。有可能会版本定义不一致报错,此配置要慎用。

node 和默认的 npm 版本对照:https://nodejs.org/zh-cn/download/releases/

.npmrc完整配置请参考: https://docs.npmjs.com/misc/config

caution

.npmrcnpm publish 的时候会自动忽略该文件

JTyPeK

See more: https://docs.npmjs.com/files/package.json

nrm

https://github.com/Pana/nrm

NPM registry manager, fast switch between different registries: npm, cnpm, nj, taobao.

npm install -g nrm

常用命令:

$ nrm ls

* npm ----- https://registry.npmjs.org/
yarn ----- https://registry.yarnpkg.com
cnpm ---- http://r.cnpmjs.org/
taobao -- https://registry.npm.taobao.org/
nj ------ https://registry.nodejitsu.com/
skimdb -- https://skimdb.npmjs.com/registry
$ nrm use cnpm  //switch registry to cnpm

Registry has been set to: http://r.cnpmjs.org/

通常,其会根据 .npmc 自动切换,虽然很方便,但在网络正常的情况下,不建议改变仓库。当然还可以自己添加公司 npm 仓库,使其能够在官方和公司自己的 npm 仓库之间可以自由切换。

npm add <registry> <url> [home]  # Add one custom registry
caution

使用 cnpm 和 taobao 的镜像的时候要注意两点:

  • 如果包安装失败,去 cnpm 或 taobao 官方仓库查看是否该包的同步有问题,可以自己手动触发与官方的同步,这点比较恼人。
  • 如果想去除 lockfile 中的 taobao 地址,不想用淘宝仓库了,最好删除 node_modulespackage-lcok.json,运行 npm cache clean --force 后再重新安装,否则可能无论怎么切换仓库地址,最后安装的还是 taobao 仓库的包,yarn 也是同理(yarn cache clean)。

lockfile

package-lock.json

重新安装模块之所以快,是因为 package-lock.json 文件中已经记录了整个 node_modules 文件夹的树状结构,甚至连模块的下载地址都记录了,再重新安装的时候只需要直接下载文件即可

详细机制注意事项请看:npm 命令和机制指南 3. 新增包

npm-shrinkwrap.json

npm@5 新增的 package-lock.json 文件和通过 npm shrinkwrap 命令生成的 npm-shrinkwrap.json 文件的格式完全相同,文件内记录了版本,来源,树结构等所有依赖的 metadata

需要注意的是 npm shrinkwrap 并不是一个新功能特性,而是从 npm@2 就开始有的功能。也就是说在 npm@5 之前的版本也是可以通过 shrinkwrap 锁定依赖的。(在这一点上,其实 Facebook 也是早期在使用 npm shrinkwrap 等功能时无法满足需求才导致了现在 yarn 的出现。可以阅读 Facebook 的这篇文章了解他们开发 yarn 的动机。)

而最新的 npm@5 在生成了 package-lock.json 之后,再运行 npm shrinkwrap 命令,会发现就是把 package-lock.json 重命名为 npm-shrinkwrap.json 而已。

因此 package-lock.json 表面上看只是把 npm-shrinkwrap.json 作为了默认创建,为何还要新建一个文件呢?官方对于此也给出了答复和解释:新增 package-lock.json 主要是为了使得 npm-shrinkwrap.json 可以向下兼容,保证旧版也可使用。另外 package-lock 的名称也比 shrinkwrap 相对更加直观。

tip
  1. 开发时提交和使用 package-lock.json 来保证不同环境、人员安装依赖的一致性。
  2. 发布包时如果有锁定的需求,可以用 npm shrinkwrap 命令把 package-lock.json 转为 npm-shrinkwrap.json 随包发布。
  3. 如果项目中已经在使用 npm-shrinkwrap.json,可以继续使用(但要注意从旧版本升级到 npm@5 后 install 时会被更新),其优先级高于 package-lock.json,并且不会再被重复创建。

Issues

node-gyp python 错误

有些使用 node-gyp 的工具不支持系统上的 Python 3,要解决这个问题,需要安装 python2并在 nvm 中设置:

npm config set python /usr/bin/python2

如果出现 gyp WARN EACCES user "root" does not have permission to access the ... dir,可以使用 --unsafe-perm 选项:

sudo npm install --unsafe-perm -g node-inspector

References

  1. Node.js (简体中文)
  2. npm CLI documentation > CLI commands npm-install
  3. The .bin folder stackoverflow
  4. npm 入门
  5. npm 模块安装机制简介
  6. 你所不知道的模块调试技巧 - npm link, 作者:atian25
  7. npx 简介, 作者:jackPan
  8. npmrc 使用小记,作者:绯雨闲丸
  9. Configuring Your .npmrc for an Optimal Node.js Environment, By Tierney Cyren
  10. npm 5 发布,有什么值得关注的新特性吗?
  11. 说说 npm 5 的新坑
  12. npm 和 yarn 缓存策略对比
  13. npm5 新版功能特性解析及与 yarn 评测对比
  14. npm CLI documentation > CLI commands npm-ci
  15. Stackoverflow: What is the closest to npm ci in yarn