版本管理

目前我们常见的NODE版本管理工具主要有三种,nvm,nvs以及n;

nvm和nvs目前都能做到跨平台,而n作为一个node模块,好像在windos下会有一些问题。

nvm也会在某些版本操作时出现node下载成功,但是npm对应版本下载失败,不知道是否是特例,我自己没有遇到过。

nvs目前来看是在nvm相关经验的基础上开发的,命令相对简单明了,但是项目自动切换命令不能持久化,关闭后在打开得重新输入。

NVM

Node版本管理器nvm,可以运行在多种操作系统上。很方便的对Node版本进行切换与管理。

安装

Windos

最新下载地址:
https://github.com/coreybutler/nvm-windows/releases

而这里又有四个可下载的文件。

  • nvm-noinstall.zip: 这个是绿色免安装版本,但是使用之前需要配置
  • nvm-setup.zip:这是一个安装包,下载之后点击安装,无需配置就可以使用,方便。
  • Source code(zip):zip压缩的源码
  • Sourc code(tar.gz):tar.gz的源码,一般用于*nix系统
MAC OS和LINUX

nvm脚本地址

  1. 运行
1
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash

或者

1
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash

建议使用curl的方式,安装后将创建目录~/.nvm并将内容存放在这里。

安装完成后关闭终端,重新打开终端输入 nvm 验证一下是否安装成功,当出现“Node Version Manager”时,说明已安装成功。

如果在新的终端输入 nvm 时提示:command not found: nvm,有可能是以下原因之一:

你的系统可能缺少一个 .bash_profile 文件,你可以创建一个此文件(可通过vi或vim命令),打开复制粘贴以下代码(安装nvm成功后终端的最后3行代码)进去,保存,然后再次运行安装命令;

1
2
3
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion

注意:如果你安装了 oh my zsh ,需要在 .zshrc 文件去添加以上配置信息,(一般安装成功都会自动写入这个文件最底部)如下图示:

  • 你可能需要重新打开一个 terminal 窗口或标签页

如果上面没有解决问题,打开你的 .bash_profile 文件,并添加以下代码:

1
source ~/.bashrc

更改完记得保存.

检测

检查是否安装成功,我们可以在新的命令窗口中输入

1
nvm -v

如果出现nvm版本号和一系列帮助指令,则说明nvm安装成功。

否则,可能会提示nvm: command not found

常用命令

  • nvm arch [32|64] : 显示node是运行在32位还是64位模式。指定32或64来覆盖默认体系结构。

  • nvm install <version> [arch]: 该可以是node.js版本或最新稳定版本latest。(可选[arch])指定安装32位或64位版本(默认为系统arch)。设置[arch]为all以安装32和64位版本。在命令后面添加–insecure ,可以绕过远端下载服务器的SSL验证。

  • nvm list [available]: 列出已经安装的node.js版本。可选的available,显示可下载版本的部分列表。这个命令可以简写为nvm ls [available]。

  • nvm on: 启用node.js版本管理。

  • nvm off: 禁用node.js版本管理(不卸载任何东西)

  • nvm proxy [url]: 设置用于下载的代理。留[url]空白,以查看当前的代理。设置[url]为none删除代理。

  • nvm node_mirror [url]:设置node镜像,默认为https://nodejs.org/dist/.。我建议设置为淘宝的镜像https://npm.taobao.org/mirrors/node/

  • nvm npm_mirror [url]:设置npm镜像,默认为https://github.com/npm/npm/archive/。我建议设置为淘宝的镜像https://npm.taobao.org/mirrors/npm/

  • nvm uninstall <version>: 卸载指定版本的nodejs。

  • nvm use [version] [arch]: 切换到使用指定的nodejs版本。可以指定32/64位[arch]。nvm use <arch>将继续使用所选版本,但根据提供的值切换到32/64位模式的<arch>

  • nvm root [path]: 设置 nvm 存储node.js不同版本的目录 ,如果未设置,将使用当前目录。

  • nvm version: 显示当前运行的nvm版本,可以简写为nvm v

切换默认版本

1
nvm alias default stable

default 是一个默认的别名,stable也是默认的别名

把nvm 启动后默认的版本号变为了指向stable的版本号

可以通过 nvm ls ,来看这些别名指向的版本号

自动切换

我们通常使用项目过程中,一些项目必须指定版本,每次手动切换比较麻烦,我们想要能自动切换。您可以直接使用 avn 深度集成到您的 shell 中,并在更改目录时自动调用 nvm。 也可以自己简单配置,下面我们看看自己怎么配置。

编写脚本

一般我们如果是MacOS或者Linux系统,常用的shell有bash和zsh两种,我们根据自己使用的编写对应配置,我下面都是在MacOS下操作的。

  1. bash

如果您使用bash,在您的~/.bashrc文件中添加如下脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
cdnvm() {
cd "$@";
nvm_path=$(nvm_find_up .nvmrc | tr -d '\n')

# If there are no .nvmrc file, use the default nvm version
if [[ ! $nvm_path = *[^[:space:]]* ]]; then

declare default_version;
default_version=$(nvm version default);

# If there is no default version, set it to `node`
# This will use the latest version on your machine
if [[ $default_version == "N/A" ]]; then
nvm alias default node;
default_version=$(nvm version default);
fi

# If the current version is not the default version, set it to use the default version
if [[ $(nvm current) != "$default_version" ]]; then
nvm use default;
fi

elif [[ -s $nvm_path/.nvmrc && -r $nvm_path/.nvmrc ]]; then
declare nvm_version
nvm_version=$(<"$nvm_path"/.nvmrc)

declare locally_resolved_nvm_version
# `nvm ls` will check all locally-available versions
# If there are multiple matching versions, take the latest one
# Remove the `->` and `*` characters and spaces
# `locally_resolved_nvm_version` will be `N/A` if no local versions are found
locally_resolved_nvm_version=$(nvm ls --no-colors "$nvm_version" | tail -1 | tr -d '\->*' | tr -d '[:space:]')

# If it is not already installed, install it
# `nvm install` will implicitly use the newly-installed version
if [[ "$locally_resolved_nvm_version" == "N/A" ]]; then
nvm install "$nvm_version";
elif [[ $(nvm current) != "$locally_resolved_nvm_version" ]]; then
nvm use "$nvm_version";
fi
fi
}
alias cd='cdnvm'
cd $PWD

该脚本命令将从您当前的目录中搜索检测.nvmrc文件。如果找到了,就会切换其配置的那个Node版本;如果没有,它将使用默认版本。

  1. zsh

如果您使用zsh,在您的~/.zshrc文件中添加如下脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# place this after nvm initialization!
autoload -U add-zsh-hook
load-nvmrc() {
local node_version="$(nvm version)"
local nvmrc_path="$(nvm_find_nvmrc)"

if [ -n "$nvmrc_path" ]; then
local nvmrc_node_version=$(nvm version "$(cat "${nvmrc_path}")")

if [ "$nvmrc_node_version" = "N/A" ]; then
nvm install
elif [ "$nvmrc_node_version" != "$node_version" ]; then
nvm use
fi
elif [ "$node_version" != "$(nvm version default)" ]; then
echo "Reverting to nvm default version"
nvm use default
fi
}
add-zsh-hook chpwd load-nvmrc
load-nvmrc

title

保存退出。

创建版本控制文件

在您的项目中创建.nvmrc文件,填入需要切换的版本:
title

接下来每次当您进入项目目录时,nvm会帮你自动切换到对应node版本,退出目录node版本又还原了,不用每次手动操作了。

title

nvm use在包含.nvmrc文件的目录中会自动调用

zsh+package.json的另一种自动切换方案

了解package.json结构的肯定知道一个engines属性,专门用来告诉项目使用的node版本和npm版本(只是提示,无切换功能)。我们刚好借助起来。

1
2
3
4
"engines": {
"npm": "6.10.0",
"node": "10.15.3"
}
  1. 安装jq
    jq官网

  2. 编写zsh配置文件

1
2
3
4
5
6
7
8
9
10
11
12
precmd(){
if [ -f package.json ]
then
nodeVersion=$(jq -r '.engines.node | select(.!=null)' package.json )
if [ ! -z $nodeVersion ] \
&& [[ ! $(nvm current) = "^v$nodeVersion" ]]
then
echo "found $nodeVersion in package.json engine"
nvm use ${nodeVersion:0:2}
fi
fi
}

卸载NVM

  1. 执行下面的命令移除nvm内容
1
2
cd ~/.nvm
rm -rf .nvm
  1. 移除掉~/.profile ~/.bash_profile ~/.zshrc ~/.bashrc文件中关于nvm的配置

使用心得

1. 版本简写

xxx代表需要切换的版本号,实际操作中发现可以简写,比如v10.5.0可以简写为v10,甚至写为10。如果本地同时存在12.22.5和12.19.0,nvm use 12,只会默认切换到最高版本12.22.5。

2. 安装新版本node时全局模块丢失

因为nvm每个版本完全独立,所以新安装的node版本不会自动下载原node的全局模块。可以用以下方法解决:

例如安装12.0.1时将10.15.3的全局模块移植过来。

1
nvm install 12.0.1 --reinstall-packages-from=10.15.3 

3. 原生命令文档

我们经常使用的命令不是太多,但是我们可用的命令可是很多的,偷懒不做翻译和体验了,照搬文档过来。

命令 描述
nvm –help Show this message
nvm –version Print out the installed version of nvm
nvm install [-s] <version> Download and install a <version>, [-s] from source. Uses .nvmrc if available
–reinstall-packages-from=<version> When installing, reinstall packages installed in <node/iojs/node version number>
–lts When installing, only select from LTS (long-term support) versions
–lts=<LTS name> When installing, only select from versions for a specific LTS line
–skip-default-packages When installing, skip the default-packages file if it exists
–latest-npm After installing, attempt to upgrade to the latest working npm on the given node version
–no-progress Disable the progress bar on any downloads
nvm uninstall <version> Uninstall a version
nvm uninstall –lts Uninstall using automatic LTS (long-term support) alias lts/*, if available.
nvm uninstall –lts=<LTS name> Uninstall using automatic alias for provided LTS line, if available.
nvm use [–silent] <version> Modify PATH to use <version>. Uses .nvmrc if available
–lts Uses automatic LTS (long-term support) alias lts/*, if available.
–lts=<LTS name> Uses automatic alias for provided LTS line, if available.
nvm exec [–silent] <version> [<command>] Run <command> on <version>. Uses .nvmrc if available
–lts Uses automatic LTS (long-term support) alias lts/*, if available.
–lts=<LTS name> Uses automatic alias for provided LTS line, if available.
nvm run [–silent] <version> [<args>] Run node on <version> with <args> as arguments. Uses .nvmrc if available
–lts Uses automatic LTS (long-term support) alias lts/*, if available.
–lts=<LTS name> Uses automatic alias for provided LTS line, if available.
nvm current Display currently activated version of Node
nvm ls List installed versions
nvm ls <version> List versions matching a given <version>
nvm ls-remote List remote versions available for install
–lts When listing, only show LTS (long-term support) versions
nvm ls-remote <version> List remote versions available for install, matching a given <version>
–lts When listing, only show LTS (long-term support) versions
–lts=<LTS name> When listing, only show versions for a specific LTS line
nvm version <version> Resolve the given description to a single local version
nvm version-remote <version> Resolve the given description to a single remote version
–lts When listing, only select from LTS (long-term support) versions
–lts=<LTS name> When listing, only select from versions for a specific LTS line
nvm deactivate Undo effects of nvm on current shell
nvm alias [<pattern>] Show all aliases beginning with <pattern>
nvm alias <name> <version> Set an alias named <name> pointing to <version>
nvm unalias <name> Deletes the alias named <name>
nvm install-latest-npm Attempt to upgrade to the latest working npm on the current node version
nvm reinstall-packages <version> Reinstall global npm packages contained in <version> to current version
nvm unload Unload nvm from shell
nvm which [current / <version>] Display path to installed node version. Uses .nvmrc if available
nvm cache dir Display path to the cache directory for nvm
nvm cache clear Empty cache directory for nvm

NVS

NVS 是一个跨平台实用程序,用于在nodejs不同版本和分支之间切换。NVS 本身是用 node JavaScript 编写的。

这个工具显然受到了其他节点版本管理器工具的启发,尤其是nvm,它借鉴了很多想法和一些命令行语法。

安装

以下是基本设置说明。有关设置 NVS 的更多详细信息和选项,请参阅设置页面。

Windos

Windows Installer (MSI) 包可从GitHub 上NVS 版本页面获得

你也可以使用Chocolatey来安装:

1
choco install nvs
Mac OS和Linux

指定安装路径,克隆项目,编译安装

1
2
3
4
5
6
7
8
#指定路径
export NVS_HOME="$HOME/.nvs"

#克隆项目
git clone https://github.com/jasongin/nvs "$NVS_HOME"

#编译安装
. "$NVS_HOME/nvs.sh" install

nvs.sh脚本向环境添加了一个nvs shell函数。 之后,该工具可以作为不用指向路径的 nvs 直接调用。 install 命令会在~/.bashrc~/.profile~/.zshrc 文件中添加配置,以便 nvs 命令在你的shell 中可用。

基本用法

添加最新版本的节点:

1
$ nvs add latest

或者添加最新的节点 LTS 版本:

1
$ nvs add lts

然后运行nvs use命令将 node 版本添加到当前 shell 的 PATH 中:

1
2
$ nvs use lts
PATH += ~/.nvs/node/6.9.1/x64

要将其永久添加到 PATH,请使用nvs link

1
$ nvs link lts

命令参考

命令 描述
nvs help <command> 获取命令的详细帮助
nvs install 初始化您的配置文件以使用 NVS
nvs uninstall 从配置文件和环境中删除 NVS
nvs --version 显示 NVS 工具版本
nvs add [version] 下载并解压节点版本
nvs rm <version> 删除节点版本
nvs migrate <fromver> [tover] 迁移全局模块
nvs upgrade [fromver] 升级到最新的主要版本补丁
nvs use [version] 在当前 shell 中使用节点版本
nvs auto [on/off] 根据cwd自动切换
nvs run <ver> <js> [args...] 使用节点版本运行脚本
nvs exec <ver> <exe> [args...] 使用节点版本运行可执行文件
nvs which [version] 显示节点版本二进制文件的路径
nvs ls [filter] 列出本地节点版本
nvs ls-remote [filter] 列出可供下载的节点版本
nvs link [version] 链接一个版本作为默认值
nvs unlink [version] 删除指向默认版本的链接
nvs alias [name] [value] 设置或调用版本别名
nvs remote [name] [value] 设置或调用下载基本 URI

版本或过滤器由完整或部分语义版本号或版本标签(“lts”、“latest”、“Argon”等)组成,可选地前面有一个远程名称,可以选则后面跟一个架构,用斜线分隔。 示例:“lts”、“4.6.0”、“6/x86”、“node/6.7/x64”。

有关每个命令的更多详细信息,请参阅文档

交互式菜单

当不带参数调用时,nvs显示用于切换和下载节点版本的交互式菜单。

菜单

NVS 使用console-menu,这是一个最初为此项目编写的模块,然后单独发布。

VS Code代码支持

Visual Studio Code 可以使用NVS选择在启动或调试时使用的节点版本。在launch.json.vscode位于项目根文件夹的文件夹中)中,添加一个runtimeArgs带有 NVS 版本字符串的"runtimeExecutable"属性和一个引用nvs.cmd(Windows) 或nvs(Mac、Linux)的属性。(如果NVS 不在 VS Code 的 PATH 中,你可能需要指定一个绝对路径,例如"${env:HOME}/.nvs/nvs"。)

示例: 配置launch.json以便 VS Code 使用 NVS 启动节点版本 6.10:

1
2
3
4
5
6
7
8
9
10
11
12
13
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${file}",
"args": [ ],
"runtimeArgs": [ "6.10" ],
"windows": { "runtimeExecutable": "nvs.cmd" },
"osx": { "runtimeExecutable": "nvs" },
"linux": { "runtimeExecutable": "nvs" }
},
]

或者,从runtimeArgs中删除版本字符串以从项目目录中的 .node-version文件中获取版本。 有关更多详细信息,请参阅 NVS VS Code 文档 或运行 nvs help vscode。

配置远程

nvs remote命令允许配置多个远程下载位置。NVS 分别管理来自不同位置的版本,因此不存在版本冲突的风险。默认情况下,有一个指向 Node.js 官方版本的远程:

1
2
3
$ nvs remote
default node
node https://nodejs.org/dist/

这使得从其他来源获取构建成为可能。以下命令为nightly构建时添加一个远程条目,列出nightly构建,并添加一个构建:

1
2
3
4
5
$ nvs remote add nightly https://nodejs.org/download/nightly/
$ nvs lsr nightly/13
nightly/13.1.1-nightly20191120c7c566023f
...
$ nvs add nightly/13

支持其他远程源,例如:

1
2
nvs remote add iojs https://iojs.org/dist/
nvs remote add chakracore https://nodejs.org/download/chakracore-release/

别名

别名是指远程名称和语义版本的组合(处理器架构不是别名)。设置别名时,远程名称可能会被省略,在这种情况下,别名指的是默认远程。在任何其他命令中,可以使用别名代替版本字符串。

1
2
3
4
5
6
7
8
9
$ nvs alias myalias 6.7.0
$ nvs alias
myalias default/6.7.0
$ nvs run myalias --version
v6.7.0
$ nvs which myalias
~/.nvs/node/6.7.0/x64/bin/node
$ nvs which myalias/32
~/.nvs/node/6.7.0/x86/bin/node

自动切换

在 Bash 或 PowerShell 中,当您更改目录时,NVS 可以自动切换当前 shell 中的节点版本。该功能默认关闭;让它运行nvs auto on。之后,每当您cdpushd在包含.node-version.nvmrc文件的目录下时,NVS 都会相应地自动切换节点版本,并在必要时下载新版本。当你cd出去,没有.node-version.nvmrc文件的地方,那么默认(链接)版本将恢复。

1
2
3
4
5
6
7
8
9
10
11
~$ nvs link 6.9.1
~/.nvs/default -> ~/.nvs/node/6.9.1/x64
~$ nvs use
PATH += ~/.nvs/default/bin
~$ nvs auto on
~$ cd myproject
PATH -= ~/.nvs/default/bin
PATH += ~/.nvs/node/4.6.1/x64/bin
~/myproject$ cd ..
PATH -= ~/.nvs/node/4.6.1/x64/bin
PATH += ~/.nvs/default/bin

此功能在 Windows 命令提示符中不可用。请改用 PowerShell。

手动切换使用 .node-version

如果您的 shell 与自动切换不兼容,或者您更喜欢手动切换但仍然利用任何.node-version.nvmrc文件,您可以nvs use使用该版本auto运行或直接运行nvs auto.

1
$ nvs use auto

相当于

1
$ nvs auto

卸载NVS

  1. 执行下面的命令移除nvs内容
1
2
cd ~/.nvs
rm -rf .nvs
  1. 移除掉~/.profile, ~/.bash_profile, ~/.zshrc, ~/.bashrc文件中关于nvs的配置

n模块

还有一个node的版本管理工具很好用,n模块,他是一个npm包。

安装使用

  1. 首先安装n模块:
1
npm install -g n
  1. 第二步:升级node.js到最新稳定版
1
n stable

n后面也可以+版本号比如:

1
2
3
n v8.9.1

n v9.2.0

为什么不推荐使用更简单的n模块

linux和mac用户忽略

  1. 安装报错,强制安装也不行
    title

  2. 为什么呢?

    n不兼容Windows!,n不兼容Windows!,n不兼容Windows!!!

后记:avn

前边nvs和nvm我们介绍了通过修改脚本来实现版本自动切换,上边还提到一个更简单的模块来使用,它就是avn。

支持nvm和n的切换。但是他和上边修改命令不一样的点在于,上边方法只有进入对应目录才使用指定版本,退出目录还原默认版本。此方法进入对应目录,切换对应版本,但是退出目录,依旧是此版本,只有shell窗口重启才还原为默认。

但是,经过我在zsh+nvm+node(14.x.x)下测试,此模块目前有兼容性问题,就是您安装此模块的主版本必须是10.x.x,更高版本估计哪个依赖项有问题,后边有时间找找。

但是如果你采用nvm进行版本切换,可以借助exec命令解决问题。n应该也有对应指定版本下载的模块的方法。

官方安装(主版本高于10会出问题,截止到2021.10.31未修复)

1
2
npm install -g avn avn-nvm avn-n
avn setup

借助nvm

本地通过nvm先安装一个10.x.x的版本。本人为10.15.3

1
2
nvm exec 10.15.3 npm install -g avn avn-nvm avn-n
nvm exec 10.15.3 avn setup

使用

在项目目录撞见.node-version文件,填入需要的node版本。

现在,当您cd进入带有.node-version文件的目录时,avn将自动检测更改并使用您安装的版本管理器切换到该版本的node。

插件解释

avn 支持以下版本管理器:

1
2
3
nvm 通过 avn-nvm
n 通过 avn-n
nodebrew 通过 avn-nodebrew

后记

还有好多使用细节以及鉴于目前自己水平的局限性,文章不能做到万无一失和紧跟新技术发展,如有错误请大家指责并回复我,一起成长。

之后还准备写一篇npm相关的文章,和本篇文章结合起来。

欢迎大家访问我的官网
DLLCNX