nvm & npm 使用教程

nvm

这里推荐使用nvm进行node的版本管理,进行多版本切换比较方便。

What | 是什么

node version manager – node版本管理工具,可以同时切换node的多个版本在本地运行。

How | 如何使用

1.安装nvm
以curl为例,打开终端,复制粘贴如下命令后,按回车键等待安装完成即可。

1
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.3/install.sh | bash

2.安装node.js
使用nvm install <version> [<arch>]命令下载需要的版本。arch参数表示系统位数,默认是64位,如果是32位操作系统,需要执行命令:nvm install 10.0.1 32

1
$ nvm install 10.0.1

3.使用nvm管理node版本

使用特定node版本
执行nvm use <version> [<arch>] 命令开始使用特定版本。比如:nvm use 6.9.0或者nvm use 6.9.0 32

1
$ nvm use 6.9.0

切换node使用版本
刚刚下载了node 6.9.0版本并且成功使用,现在我们下载一个6.10.3版本,然后切换并使用。

1
2
3
$ nvm use 6.9.0
$ nvm install 6.10.3
$ nvm use 6.10.3

参考:
nvm官网
nvm的介绍及使用
Install nvm on Mac OSX

npm

What | 是什么

npm有几重含义,npm是世界最大的软件仓库,仓库地址为:https://www.npmjs.com,同时,npm是node的模块管理器,全称node version manager。

作为软件仓库,它由三部分构成:

  • 网站:发现包、访问和管理软件包
  • CLI:开发者与npm交互的方式
  • 注册表:JavaScript代码公共数据库和元信息

How | 如何使用

下载和安装Node.js和npm

为了可以发布和安装包,我们需要一个Node版本管理器,官方建议使用Node version manager去安装Node.js和npm。

使用nvm安装Node.js和npm
nvm可以在系统安装和切换多个Node.js和npm版本,来确保它们可以在不同的版本中使用。

前面我们已经介绍过nvm的安装和使用。

下载最新版本的npm

1
$ [sudo] npm install npm -g

检查npm和Node.js的版本

1
2
$ node -v
$ npm -v

npm CLI 版本
npm有两个版本:
稳定版lastest release 和预发布版 next release

安装Node.js的时候npm会被自动安装,然而npm比Node.js的发布要频繁,安装最新稳定版:

1
$ npm install npm@lastest -g

安装预发布版本:

1
$ npm install npm@next -g

不一定安装成功,取决于开发周期,所以可能仍然安装的是稳定版。

使用npm安装模块

因为有了npm,只需要一条命令,就能安装别人写好的模块。

1
$ npm install

安装package.json文件内的依赖模块到node_modules目录。

如果想要安装某个特定的模块,使用:

1
$ npm install <packageName>

安装前,npm install 会检查node_modules目录之中是否已经存在指定模块。如果存在,就不再重新安装了,即使远程仓库有一个新版本,也是如此。

如果你希望,一个模块不管是否安装过,npm都强制重新安装,可以使用-f--force参数。

1
$ npm install <packageName> --force

包和模块介绍

软件包和他们的元信息存放在npm的注册表里,
模块是node_modules目录中可以由Node.js require()函数加载的任何文件或目录。

关于贡献包到注册表的语意版本控制
语义化版本规格是一套规范,来帮助其他开发者理解你代码的变动程度。

它以1.0.0作为新版的开始。

阶段 代码状态 规则 版本样例
新品 第一次发布 1.0.0开始 1.0.0
补丁发布 向后兼容bug修复 增加第三个数字 1.0.1
小版本 向后兼容新功能 增长中间的数字并重置最后一个数字为0 1.1.0
主要发布 改变破坏了向后兼容 增长第一个数字并且将中间和最后一个数字重置为0 2.0.0

你可以使用语义版本去指定你包能接受的更新类型

你可以从依赖你包的package.json文件里指定你的包的更新类型。

比如,为了指定可以接受的版本范围上限是1.0.4,使用如下语法:

  • 补丁发布: 1.0 或1.0.x 或 ~1.0.4
  • 小版本:1 或 1.x 或 ^1.0.4
  • 主要发布: * 或 x

例如:

1
2
3
4
"dependencies": {
"my_dep": "^1.0.0",
"another_dep": "~2.2.0"
}

对于语意版本语法的更多信息,看npm 语意化版本计算

从注册表获取包

包的搜索和下载

打开npm官网搜索框搜索对应包的名称即可,搜索完对应的包名后,左边有四个筛选条件:

Popularity:流行度,表示该包多少次被下载,代表多少人受益了。
Quality:品质,包含了一些注意事项如果存在README文件,如稳定性,测试、最新依赖、自定义网站,代码复杂性
Maintenance:维护性,从开发人员对包的关注度来排名,例如:经常维护可能会更好。
Optimal:理想的,可以理解为前三项的综合评估,一般用这个标准就可以,这也是默认排序

安装一个没有作用域的包

这类包总是公共的,可以被任何人下载、安装。

1
$ npm install <pageage_name>

在当前目录创建node_modules(如果没有)并且下载该包到当前目录。就是在自己的项目里依赖自己的包,这也是npm install的默认行为。

注意:
如果没有本地没有package.json文件,会安装最新版本,否则,安装package.json文件中声明的满足语意规则的最新版。

安装一个作用域公共包
作用域包的下载需要引用一下作用域的名字

1
npm install @scope/package-name

测试包的安装
在你的安装目录下检查是否有node_modules包存在,这里包含了你安装包的目录

1
ls node_moudules

使用dist-tags安装包
默认是安装包的最新版,可以使用npm install <package_name>@覆写这个行为,比如安装example-package被标记为beta的版本。

1
npm install example-package@beta

下载安装全局包

顾名思义,全局包的作用域是整个电脑系统级别的。即可以在各个项目中使用它。

1
npm install -g <package_name>

注意
如果npm的版本大于等于5.2,建议使用npx来安装全局包
关于npx,看这篇文章npx介绍

如果全局安装出现了EACCES权限错误,推荐重新安装npm,或手动改变npm的默认目录,具体查看解决全局安装包EACCES权限错误

下载包的更新

更新本地安装包

  1. 找到项目根目录确保包含package.json文件:

    1
    $ cd /path/to/project
  2. 运行更新命令

    1
    $ npm update

它会先到远程仓库查询最新版本,然后查询本地版本。如果本地版本不存在,或者远程版本较新,就会安装。
单独更新某一个包,使用:

1
$ npm update <packageName>

  1. 测试更新,不应该有任何输出
    1
    $ npm outdated

更新全局安装包

决定哪个全局包需要更新

1
$ npm outdated -g --depth=0

更新某一个全局包

1
$ npm update -g <package_name>

更新所有全局包

1
$ npm update -g

注册表

npm update命令怎么知道每个模块的最新版本呢?

答案是npm模块仓库提供了一个查询服务,叫做registry。以npmjs.com为例,它的查询服务地址是https://registry.npmjs.org/

这个网址后面跟上模块名,就会得到一个JSON对象,里面是该模块的所有版本信息。比如,访问https://registry.npmjs.org/react,就会看到react模块所有版本的信息。

它跟下面命令的效果是一样的。

1
2
3
4
5
6
$ npm view react

// npm view 的别名
$ npm info react
$ npm show react
$ npm v react

registry网址的模块名后面,还可以跟上版本号或者标签,用来查询某个具体版本的信息。比如,访问 https://registry.npmjs.org/react/v0.14.6,就可以看到React的0.14.6版。

返回的JSON对象里面,有一个dist.tarball属性,是该版本的压缩包的网址。

1
2
3
dist
.tarball https://registry.npm.taobao.org/element/download/element-0.1.4.tgz
.shasum: 1642279061328a574a692e0e5184e62c180a6685

到这个网址下载压缩包,在本地解压,就得到了模块的代码。npm installnpm update命令,都是通过这种方式安装模块的。

包和依赖的卸载

卸载本地包

从node_modules目录删除本地包

1
2
3
4
// 没有作用域的包
npm uninstall <package_name>
// 包含作用域的包
npm uninstall <@scope/package_name>

例如:

1
npm uninstall lodash

从package.json依赖删除本地包
从package.json的依赖里删除包,使用 –save标志。

1
2
3
4
// 非作用域包
npm uninstall --save <package_name>
// 作用域包
npm uninstall --save <@scope/package_name>

例如

1
npm uninstall --save lodash

注意
如果安装包作为一个“devDependency”(i.e. 用 –save-dev),使用 –save-dev 去卸载它: npm uninstall –save-dev package_name

删除确认
查看包是否已删除

  • (OS X): ls node_modules

卸载全局包

需要加一个g标志

1
2
3
4
// 非作用域包
npm uninstall -g <package_name>
// 作用域包
npm uninstall -g <@scope/package_name>

其他

问题排查

我们可以在安装包的使用生成一个debug.log文件,该文件会在安装失败的时候生成,帮我们排查错误,如果需要生成这个文件,安装包时,使用如下命令:

1
$ npm install --timing

debug.log文件位于.npm目录。可以使用npm config get cache发现这个目录。

npm 设置淘宝镜像

参考:如果npm太慢,设置淘宝npm镜像使用方法

因为npm服务器在国外,如果觉得慢,可以换成淘宝NPM镜像

将npm的registry设置为淘宝的镜像源,以下为几种常用方法:

  1. 临时使用

    1
    npm --registry https://registry.npm.taobao.org install express
  2. 持久使用

    1
    npm config set registry https://registry.npm.taobao.org

回复原地址使用:

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

配置成功后验证:
npm config get registrynpm info express

  1. 通过cnpm使用
    1
    npm install -g cnpm --registry=https://registry.npm.taobao.org

使用样例

1
cnpm install express

缓存目录

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

这个缓存目录,在Linux或Mac默认是用户主目录下的.npm目录,在Windows默认是%AppData%/npm-cache。通过配置命令,可以查看这个目录的具体位置。

1
2
$ npm config get cache
/Users/zhangfeilong/.npm

你最好浏览一下这个目录。

1
$ ls ~/.npm

可以使用如下命令查看该目录下内存大小:

1
du -sh *

.npm目录存放着大量文件,清空它的命令。

1
2
3
$ rm -rf ~/.npm/*
# 或者
$ npm cache clean

模块的安装过程

总结一下,Node模块的安装过程是这样的:

  1. 发出npm install命令
  2. npm向registry查询压缩包的网址
  3. 下载压缩包,存放在~/.npm目录
  4. 解压压缩包到当前目录的node_modules目录

注意,一个模块安装以后,本地其实保存了两份。一份是 ~/.npm目录下的压缩包,另一份是node_modules目录下解压后的代码。

但是,运行npm insall的时候,只会检查node_modules目录,而不会检查~/.npm目录。也就是说,如果该模块在~/.npm下有压缩包,但是没有安装在node_modules目录中,npm依然会从远程仓库下载一次新的压缩包。

这种行为固然可以保证总是取得最新的代码,但有时并不是我们想要的。最大的问题是,它会极大的影响安装速度。即使某个模块的压缩包就在缓存目录中,也要去远程仓库下载,这怎么可能不慢呢?

另外,有些场合没有网络(比如飞机上),但是你想安装的模块,明明就在缓存目录之中,这时也无法安装。

–cache-min参数

为了解决这些问题,npm提供了一个 --cache-min参数,用于从缓存目录安装模块。

--cache-min参数指定一个时间(单位为分钟),只有超过这个时间的模块,才会从registry下载。

1
$ npm install --cache-min 99999 <package-name>

上面命令指定,只有超过99999分钟的模块,才从registry下载。实际上就是指定,所有模块从缓存安装,这样就大大加快了下载速度。

它还有另一种写法。

1
$ npm install --cache-min Infinity <package-name>

但是,这并不等于离线模式,这是仍然需要网络连接。因为现在的--cache-min实现有一些问题。

(1) 如果指定模块不在缓存目录,那么npm会连接registry,下载最新版。这没有问题,但是如果指定模块在缓存目录之中,npm也会连接registry,发出指定模块的etag,服务器返回状态码304,表示不需要重新下载压缩包。
(2) 如果某个模块已经在缓存之中,但是版本低于要求,npm会直接报错,而不是去registry下载最新版本。

npm团队知道存在这些问题,正在重写cache。并且,将来也会提供一个--offline参数,使用npm可以在离线情况下使用。

不过,这些改进没有日程表。所以,当前使用 --cache-min改进安装速度,是有问题的。


参考:
npm模块安装机制简介
npm官网