Node.js环境管理器的比较

2,215 阅读6分钟

在从事JavaScript项目时,经常会出现一个麻烦,那就是管理构建或运行一个项目所需的不同版本的工具。这基本上可以归结为这样一个事实,即不同的项目对其依赖性有不同的版本要求。例如,一个绿地项目可能需要最新版本的Node.js,因为它使用了一个实验性的功能,而一个传统的项目可能依赖于过时的功能,使它无法在较新的版本上运行。

安装不同版本的Node.js或其他软件包通常需要卸载当前的版本,然后安装需要的版本,然后在项目之间切换时重复这个过程。这就是虚拟环境管理器的价值主张变得明显的地方。它们提供了一个隔离的环境,允许安装一个软件包的几个版本,这样就可以很容易地为一个项目使用一个特定版本的软件包,而不影响其他依赖同一软件包不同版本的应用程序。

在这篇文章中,我们将研究一些最常见的Node.js的虚拟环境管理器,并描述它们的特点,以及每一种的优点和缺点。读完这篇作品,你将有足够的背景来选择最适合你的环境管理器

1.Node版本管理器(NVM)

Node版本管理器是在Linux或macOS系统上安装、升级和管理Node.js版本的最流行方式。通过其安装脚本 安装NVM后,它将修改你的shell配置文件,如.bashrc.zshrc ,以便在随后的每次shell调用中正确加载。一旦有了nvm 命令,你就可以用它在终端上输入nvm install node ,来安装最新的Node.js版本。

NVM支持同时安装几个版本的Node.js,并且很容易在你所安装的不同版本之间进行切换。你可以通过在install 子命令中指定版本号来安装一个特定的Node.js版本,你可以通过use 子命令在已安装的版本之间进行切换。下面是一些有用的NVM命令,你可能想看看:

$ nvm install 16.6.2 # install Node.js v16.6.2
$ nvm use 16.5.0 # switch to version 16.5.0 on the current shell instance
$ nvm alias default 16.6.2 # set the default version for new shell instances
$ nvm ls-remote # list all available versions
$ nvm ls # list all installed versions
$ nvm # view nvm usage information

使用NVM来安装Node.js而不是你的操作系统的软件包管理器的一个优势是能够在不提升权限的情况下全局安装npm包。这意味着你不再需要在全局安装软件包的命令前加上sudo 。全局包的范围是当前的Node.js版本,并安装到$HOME/.nvm/versions/node/<version>/bin/ 。这样做的结果是,当你切换到不同的Node.js版本时,它们就无法被访问。为了解决这个问题,NVM提供了一种在安装不同版本时迁移全局软件包的方法。

NVM在它所做的事情上是非常棒的,但它也有一些不足之处。例如,它只支持符合POSIX标准的shell,如bash或zsh,把流行的Fish shell的用户晾在一边。对Windows的支持也很缺乏,除非你使用Windows Subsystem for Linux(WSL)或像Cygwin这样的项目。人们还观察到,NVM使shell的初始化速度降低了几毫秒,这在某些系统上可能是明显的。与这个名单上的其他一些选项相比,这些都是不选用NVM的原因。

2.N

名字很奇怪的n项目是另一种流行的方式,可以在一台机器上管理多个Node.js版本。n 是一个node.js模块,所以它可以通过npm 。这意味着需要一个现有的Node.js安装(也许是由你的操作系统的包管理器提供的)来安装它,因为npm 通常是与Node一起的。也有一些第三方安装程序可以帮助你安装n ,而不需要Node.js或npm

一旦你下载了n ,你可以用它来安装、升级和管理Node.js版本。它的工作原理是下载(和缓存)特定版本的预建二进制文件到/usr/local 内的n/versions/node 目录,然后将其安装到/usr/local/bin 目录,这具有覆盖任何现有版本的效果。注意,在使用n 安装Node.js版本时,你可能需要使用sudo ,以避免权限错误。在项目的README文档中提供了一些避免使用sudo 进行nnpm 全局安装的指导

Terminal showing sudo requirement for using n

与NVM相比,n的管理Node.js发布的方法的主要优势是,当你在不同版本的Node之间切换时,全局npm 包不会受到影响。另一方面,NVM允许你通过其nvm use 命令在不同的终端使用不同的Node.js版本,而n 则不能。一旦你切换到一个不同的Node.js版本,这个变化就会在系统中反映出来。你可以通过使用n use 子命令来调用一个特定的Node.js二进制文件而不切换到该版本。这在执行一次性的脚本执行时可能会很方便。

$ cat index.js
console.log(`Current Node.js version is: ${process.version}`);
$ node --version
v16.7.0
$ node index.js
Current Node.js version is: v16.7.0
$ n use 16.6.2 index.js
Current Node.js version is: v16.6.2

3.快速节点管理器(FNM)

Fast Node Manager是一个用Rust编写的跨平台Node.js版本管理器,声称比NVM快40倍,同时提供大部分相同的功能。与其前身不同的是,也许是由于其Rust的起源,对Windows(Powershell)和Fish shell的支持都是存在的,这使得它适合于更多的用户。

一旦FNM被安装,其使用方法与NVM类似。你可以在这个GitHub文档中检查该工具提供的所有可用命令。

$ fnm ls-remote # list remote Node.js versions
$ fnm install 16.5.0 # install a specific version
$ fnm use 14.17.5 # switch Node.js version
$ fnm ls # list installed versions
$ fnm default <version> # set a default version

FNM将Node.js二进制文件安装在$HOME/.fnm/node-versions 目录下,并在shell启动时将它们象征性地链接到/tmp/fnm_multishells 目录下,这样你就可以在每个shell使用不同的Node.js版本。全局包的行为也与NVM相同,这意味着它们与特定版本的Node.js绑定,一旦当前的Node.js版本被改为不同的版本,它们将无法被访问。

由于FNM支持.node-version.nvmrc文件格式,为项目设置正确的Node.js版本,因此从NVM或其他版本管理程序迁移到FNM应该是无缝的。一旦任一文件出现在一个目录中,你可以运行fnm use ,以改变为指定的Node.js版本。如果该版本没有安装,你会被提示安装它.

Terminal showing an FNM auto switching Node.js version

当你改变一个目录时,自动切换Node.js版本也是可能的,尽管它涉及一些额外的设置。你需要运行fnm env --use-on-cd ,以打印出设置自动切换所需的脚本,然后将其复制到你的shell的适当配置文件(.bashrc,config.fish, 等等)。之后,它应该可以无缝工作,没有任何可察觉的开销。

4.沃尔塔

Volta是一个相对较新的JavaScript工具管理器,它的作用不仅仅是安装和管理Node.js版本。像FNM一样,它是用Rust编写的,它支持Unix系统和Windows。安装Volta非常容易;为Unix系统提供了一个脚本,为Windows提供了一个安装程序。

Volta的主要价值主张是,它可以根据项目的package.json 文件,通过跟踪所需的确切软件包版本来管理整个JavaScript工具链。在引擎盖下,Volta使用一个垫片来引导到工具的正确版本,并通过适当的Node.js引擎来执行它。例如,Node.js包可以通过其install 命令为当前用户全局安装。

$ volta install yarn@1.22.11
success: installed and set yarn@1.22.11 as default
$ volta install jest
success: installed jest@27.0.6 with executables: jest
$ volta install typescript
success: installed typescript@4.3.5 with executables: tsc, tsserver

Screenshot of Volta commands

在Unix系统上,每个工具的二进制文件被下载到用户的主目录下的.volta/bin 。在Windows上,下载二进制文件的位置可能有所不同,这取决于你如何安装Volta。在用Volta安装一个软件包后,你将能够直接在终端运行它,就像你通过npm 全局安装它一样。当你换到一个有相同软件包作为依赖的项目时,Volta会自动无缝切换到本地安装的版本以保证兼容性。

$ tsc --version
Version 4.3.5
$ cd node_project
$ cat package.json | grep 'typescript'
  "typescript": "^4.0.8",
$ tsc --version
Version 4.0.8

注意我们是如何在不改变正在运行的命令的情况下得到正确的版本的。这是Volta相对于之前考察的环境管理器的主要优势之一。如果你选择通过npmyarn 而不是volta install 来全局安装软件包,这个功能也以同样的方式工作。 Volta将根据需要在全局和本地安装的变体之间自动切换。

你也可以使用Volta来安装和管理Node.js版本。下面的命令将安装最新版本的Node.js。如果你省略了@latest 后缀,将下载最新的LTS版本。

$ volta install node@latest
success: installed and set node@16.7.0 (with npm@7.20.3) as default

一旦指定的Node.js版本被安装,它随后也会被设置为全局默认版本,正如在上面的命令输出中观察到的那样。如果你想保证对一个项目使用特定的Node.js版本,你可以使用Volta通过其pin 子命令指定所需的版本。

$ volta pin node@14.17.5
success: pinned node@14.17.5 (with npm@6.14.14) in package.json

这将在项目的package.json 文件中添加以下条目。

"volta": {
  "node": "14.17.5"
}

有了上述条目,任何使用Volta的人在cd 进入项目目录时,都会自动获得package.json 文件中指定的正确Node.js版本。如果本地没有相应的Node.js版本,将直接下载并安装。

$ node --version
v16.7.0
$ cd node_project
$ cat package.json | grep 'volta' -A 2
  "volta": {
    "node": "14.17.5"
  },
$ node --version
v14.17.5

5.Asdf

Screenshot of Asdf homepage

与到目前为止讨论的所有其他工具不同,Asdf不是专门针对Node.js生态系统的。它是一个在每个项目基础上管理多个语言运行时版本的工具,它的目的是取代特定语言的环境管理器,如nvmrbenvpyenv 。如果你用几种语言开发应用程序,并且需要一种更有效的方式来管理每种语言的环境,而不是玩弄几种不相关的工具,Asdf可能是你的正确选择。

Asdf只支持Linux和macOS,所以你无法在Windows上使用它,除非通过WSL。在安装了核心CLI之后,你需要为你感兴趣的语言安装插件。Asdf为Node.js、Ruby、Elixir和Erlang提供了第一方插件,而其他语言则通过社区驱动的插件支持。这里是你安装Asdf的Node.js插件所需的命令。

$ asdf plugin add nodejs https://github.com/asdf-vm/asdf-nodejs.git

一旦你安装了相关的插件,你就可以为该工具安装一个版本,比如最新的Node.js版本。

$ asdf install nodejs latest

设置默认的Node.js版本可以通过Asdf的global 子命令实现:

$ asdf global nodejs latest

这将在$HOME/.tool-versions 文件中添加以下一行:

$ cat ~/.tool-versions
nodejs 16.7.0
$ which node
/home/<user>/.asdf/shims/node

如果你依赖全局npm包,你可以在$HOME/.default-npm-packages ,以便在安装每个Node.js版本后自动安装它们:

$ cat ~/.default-npm-packages
create-react-app
eslint
@ayoisaiah/f2

要在项目中利用特定版本的Node.js,你需要在项目目录中运行asdf local nodejs <version> 。如果该版本没有安装,你需要先用asdf install nodejs <version> 来安装它。之后,一旦你cd 到项目目录中,Asdf会自动切换到本地的node版本。

Asdf也能理解.nvmrc.node-version ,所以从其他环境管理器迁移应该是很容易的。你需要在你的$HOME/.asdfrc 文件中添加以下一行,以确保Asdf可以从这两个文件中读取。

legacy_version_file = yes

结论

在这篇文章中,我们已经介绍了很多环境管理器,很明显,它们都有类似的功能,但实现方式略有不同。无论你选择哪种方案,你都能在不同版本的Node.js之间轻松切换,升级到最新版本也是轻而易举。

我建议使用Volta,因为它具有独特的能力,可以根据项目要求在多个版本的软件包之间轻松切换,而且它支持所有主要的操作系统。如果你倾向于使用多种语言,Asdf可能是一个更好的选择,如果你想要一个更快的NVM替代品,同时支持Windows,FNM是一个不错的选择。还有其他选择,如nvsnodeenv。如果本文讨论的所有选项都不适合你,请随时查看它们。