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
Acronym
-g
--global
缩写为 -g
,表示安装之后的包将位于系统预设的全局目录之下。
-S
--save
缩写为 -S
,表示安装的包将写入 package.json
里面的 dependencies
。
-D
--save-dev
缩写为 -D
,表示将安装的包将写入 packege.json
里面的 devDependencies
。
-E
--save-exact
缩写为 -E
,表示安装的包的版本是精确指定的。比如 npm install react -E
后 dependencies
中 react 版本为:
"react": "16.13.1"
以下缩写则不是很常用,仅供参考:
-O
--save-optional
缩写为 -O
,表示将安装的包将写入 packege.json
里面的 optionalDependencies
。
-B
--save-bundle
缩写为 -B
,表示将安装的包将写入 packege.json
里面的 bundleDependencies
。
npm outdated
例如在 node 项目中运行 npm outdated
命令,如下图所示:
wanted 就是 dependencies
或 devDependencies
字段中指定的版本号应当升级的版本,可以看出上面列表 less
用的是 ^
,所以 wanted 会提示更新次要版本号。
npm install
Install package
这个是 npm 中最常用的命令:
npm install packageName
可以简写为:
npm i packageName
这个命令会将 package 安装在当前目录下 node_modules
目录内,可执行命令(如果有)安装在 node_modules/.bin
目录下。全局安装使用 -g
选项:
npm install -g packageName # npm i -g packageName
具体安装在 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.json
和 package-lock.json
。
npm i
和 npm 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.json
或npm-shrinkwrap.json
。 npm ci
永远不会写入package.json
或任何 lockfile,安装基本上是冻结的。- 如果 lockfile 中的依赖项与其中的依赖项不匹配
package.json
,npm ci
则将退出并显示错误,而不是更新 lockfile。 - 如果
node_modules
已经存在,它将在npm ci
开始安装之前自动删除。 npm ci
只能一次安装整个项目,使用此命令无法添加单个依赖包。
yarn 没有这个命令,但有一个比较类似的命令:yarn install --frozen-lockfile
npm update
更新包有两种方式 npm i packageName<@version>
或者 npm update packageName
可以简写为:
npm up packageName
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
全局安装的包可能需要管理员权限,取决于 node 的安装目录是否是 ~
。
更新所有包有时你只希望更新所有包,去掉包名将试图更新所有包。
npm up
或者添加 -g
标记更新全局环境安装的包
npm up -g
npm uninstall
删除使用 -g
标记安装的包只须:
npm uninstall packageName
可以简写为:
npm un packageName
# or
npm r packageName
对于全局安装的包 加上 -g
即可:
npm r -g packageName
全局安装的包可能需要管理员权限,取决于 node 的安装目录是否是 ~
。
npm list
若要显示已安装的包的树形视图执行:
npm list -g
可以简写为:
npm ls packageName
# or
npm ll packageName
# or
npm la packageName
若只要显示第一层结构的包(你自己安装的包),可以执行:
npm ls -g --depth=0
npm cache
npm install
或npm update
命令,从 registry 下载压缩包之后,都存放在本地的缓存目录。
npm config get cache
npm 的缓存目录是通过 cache 变量指定的,一般默认是在~/.npm
文件夹,可以执行下面的命令查看
npm config get cache
在 npm@5 以前,每个缓存的模块在 ~/.npm
文件夹中以模块名的形式直接存储,例如 koa 模块存储在~/.npm/koa
文件夹中。而 npm@5 版本开始,数据存储在 ~/.npm/_cacache
中,并且不是以模块名直接存放。
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
npm link/unlink
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
- 如果在 my-project 里面重新执行过
npm i
那么 link 就会失效,需要重新 link。 - 在 npm-package 里面的修改能自动同步到 my-project。
- 使用
nvm
的时候要注意不同项目是否用的是同一个版本的 node,否则 link 是不会生效的。
npx
- 安装
如果 npm 的版本 >=5.2.0
应该会自带 npx 命令,直接使用即可。如果没有则 npm install -g npx
。完整的命令使用说明,运行npx
即可
- 机制
- 首先会自动检查当前项目中的可执行依赖文件(即
./node_modules/.bin
下面的可用依赖) - 如果不存在就会去环境变量 path 中寻找
- 如果还没有就会自动安装,其安装的依赖位于
~/.npm/_npx
之中(_macOS@10.14, npm@6.3.0_,npm config get cache
可查看_npx
所在目录),安装的依赖只是临时的。
比如运行了 npx http-server
会在该目录下面生成 24745
,当服务停掉时,该目录会自动删除。
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 使用起来非常的方便。只需要如下几个步骤:
- 在项目根目录创建一个.npmrc 的文件
- 在这个文件中写入相关配置信息
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
.npmrc
在 npm publish
的时候会自动忽略该文件
See more: https://docs.npmjs.com/files/package.json
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
使用 cnpm 和 taobao 的镜像的时候要注意两点:
- 如果包安装失败,去 cnpm 或 taobao 官方仓库查看是否该包的同步有问题,可以自己手动触发与官方的同步,这点比较恼人。
- 如果想去除 lockfile 中的 taobao 地址,不想用淘宝仓库了,最好删除
node_modules
和package-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 相对更加直观。
- 开发时提交和使用
package-lock.json
来保证不同环境、人员安装依赖的一致性。 - 发布包时如果有锁定的需求,可以用
npm shrinkwrap
命令把package-lock.json
转为npm-shrinkwrap.json
随包发布。 - 如果项目中已经在使用
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
- Node.js (简体中文)
- npm CLI documentation > CLI commands npm-install
- The .bin folder stackoverflow
- npm 入门
- npm 模块安装机制简介
- 你所不知道的模块调试技巧 - npm link, 作者:atian25
- npx 简介, 作者:jackPan
- npmrc 使用小记,作者:绯雨闲丸
- Configuring Your .npmrc for an Optimal Node.js Environment, By Tierney Cyren
- npm 5 发布,有什么值得关注的新特性吗?
- 说说 npm 5 的新坑
- npm 和 yarn 缓存策略对比
- npm5 新版功能特性解析及与 yarn 评测对比
- npm CLI documentation > CLI commands npm-ci
- Stackoverflow: What is the closest to npm ci in yarn