URL
type
status
date
slug
summary
tags
category
icon
password
配置fnm和corepack时遇到了一些坑,记录下,包括网络问题和环境变量的配置。。。
一、为什么我们需要fnm和corepack?
fnm用于解决nodejs的版本管理问题。许多模块依赖于特定版本的nodejs,因此在一个系统里安装多个版本的nodejs就显得非常重要。fnm能让我们的系统中有多个版本的node共存,并且提供快捷的安装、切换、删除指定版本的命令。
相比于更知名的包管理工具nvm,fnm的特点是轻量、快速、跨平台,各种操作也都很直观易上手。这里有个fnm与其它node版本工具的性能对比,数据是2020年的。
fnm还可以劫持命令行的cd命令,用命令行进入某个文件夹时,自动检测当前目录下的
.node-version
文件或者.nvmrc
文件,然后自动切换到对应的版本,没有这个版本会提示你下载。corepack是管理包管理器的管理器,让我们不用担心在npm、pnpm和yarn中艰难选择。它会根据项目配置的指定版本包管理器,下载并缓存指定版本。当你在pnpm项目中使用npm,也会提示你使用正确的命令。你也可以很方便的在不同的包管理器版本中来回切换。
二、安装fnm
fnm github地址
直接根据fnm的官方文档安装,这里不多赘述:
- mac和Linux提供了自动安装脚本。
- Windows可以自行手动安装(注意,手动安装完成后记得配置shell,文档中有)
安装后命令行输入
fnm -V
(大写V),如果返回版本号就是装上了。
2.1 常用命令(和nvm类似):
命令 | 作用 |
fnm list | 列出已经安装的所有版本 |
fnm list-remote | 列出可以下载的版本 |
fnm install [版本号] | 安装指定版本,版本号可以从上一个命令中找到 |
fnm uninstall [版本号] | 有安装就有卸载 |
fnm use [版本号] | 切换到指定版本的node,版本号可以从fnm list中找到 |
fnm env [可选参数] | 打印出当前fnm依赖的环境变量,可以配置一些fnm的扩展功能,
比如我们手动安装后,就是用它设置shell |
fnm alias [版本号] [别名] | 给已经安装的某个版本加个别名,毕竟版本号记不住,
加了后就可以 fnm use [别名] 来切换版本了 |
fnm current | 忘了当前是哪个版本?用这个命令可以查看 |
[!WARNING] 注意!
fnm似乎识别中文或特殊字符路径有问题,如果你的npm安装路径中有特殊字符,可能在用
fnm use
命令切换版本时报错。报错首先排查路径是否有特殊字符或中文,修改npm路径后,一定记得同时修改环境变量。2.2 fnm如何识别当前项目的nodejs版本?
第一种方式,通过读取项目目录下的
.node-version
和.nvmrc
文件来获取当前项目的node版本,所以你可以在自己的项目下创建这个文件来约束团队的node版本。
第二种方式,当开启fnm的解析引擎后,fnm就可以读取package.json中 "engines": {"node": ">=20 <21" }
这样的字段,获取到node版本。要开启解析引擎,可以看下面fnm env的用法。2.3 fnm env的妙用
fnm env
命令后面跟上不同的参数能够修改对应的环境变量,开启不同的扩展功能。直接输入fnm env
只能查看,是不会实际起作用的,要想实际起作用,得进行一些配置,可以先看后面的环境变量配置再回来看这里。这里介绍几个官方推荐的配置:
fnm env --use-on-cd
:当你cd进入某个项目目录后,fnm会自动检测该项目的版本,然后提示你切换到对应的版本,或下载对应版本。还记得手动安装fnm后,让你配置shell时用的语句吗?那里面就默认添加了这个参数。
fnm env --version-file-strategy=recursive
:配置了这个,当我们直接 fnm use
和 fnm install
但不加任何参数,fnm就会去父文件夹中找版本文件(.node-version和.nvmrc)。
fnm env --corepack-enabled
:新安装一个nodejs版本时,会自动运行corepack enable
,也就是保证你新装的node默认开启corepack。
fnm env --resolve-engines
:如上一节所说,开启这个后能够通过package.json中的engines字段来获取版本信息。如下:[!WARNING] 注意!
fnm切换node版本,必须要读取环境变量,否则会报错!因此一定要在终端中设置环境变量。后文的环境变量部分会介绍如何自动对环境变量进行设置。
三、安装corepack
corepack github地址
corepack是nodejs官方出品。如果用的新版nodejs,那么corepack是自带的,但默认关闭,你可以启用它:
手动安装corepack可以用如下命令,再启用:
安装或启用后,命令行运行
corepack -v
,返回版本号就是装上了。3.1 corepack基本使用
corepack打开就生效了,可以直接使用,以下是官方给出的基础能力:
只需像往常一样使用你的包管理器。在 Yarn 项目中运行yarn install,在 pnpm 项目中运行pnpm install,在 npm 项目中运行npm。Corepack 会捕捉这些调用,并根据情况进行相应处理:
- 如果本地项目已为所使用的包管理器进行了配置,Corepack 将下载并缓存最新兼容版本。
- 如果本地项目配置了不同的包管理器,Corepack 将提示您使用正确的包管理器重新运行命令,从而避免安装文件损坏。
- 如果本地项目未配置任何包管理器,Corepack 将假定您知道自己在做什么,并使用已固定为“已知良好版本”的包管理器版本。查看相关部分了解更多详情。
为项目指定包管理器:在package.json中设置 "packageManager"字段,然后写上指定包管理器,示例如下:
上面设置的字符串包含包管理器名称、版本和用于验证的哈希值。
corepack的环境变量: corepack也有许多的环境变量,这些环境变量配置corepack的下载仓库地址、指定包管理器的位置、设置代理地址等等。详细可以看文档:corepack环境变量
更多功能和实用命令可以直接看github的文档。
四、环境变量设置
fnm和corepack都会通过读取环境变量来配置一些功能。而不同的环境下设置环境变量的方式不同,我们可以参考fnm配置shell的部分一窥究竟。
4.1 环境变量分类
环境变量就是一些供程序读取的值,通常是一个键值对,比如
KEY=value
,主要有临时的和持久化的两种环境变量。
临时环境变量: 通常是在打开的终端中设置的,终端关闭后就销毁了,并且只能这个终端读取,其它终端无法访问。
持久化的环境变量: 是存在系统的文件里面的,只要你不主动删除,随时都能读取,每个终端都能读取。而持久化的环境变量,分为用户级别和系统级别。我们知道现代操作系统都支持多用户,因此用户级别的环境变量只能指定用户访问,而系统级别的每个用户都能访问。
在不同的系统和不同的终端程序中,设置环境变量的方法各不相同。4.2 Linux/Mac
临时环境变量设置:
通过export进行设置,当前终端会话关闭后,这些环境变量也没了。
持久化环境变量:
Linux和Mac系统有个启动脚本文件,每次打开终端,就会先执行这个文件中的命令。因此可以使用
echo xxx >> 启动脚本文件
把设置临时环境变量的命令写入这个脚本中,相当于每次打开终端都设置下这些环境变量。不同的系统下有不同的启动脚本文件,用户级和系统级也分不同的启动脚本文件,可以自行查阅或问ai。
4.3 Windows
Windows下有好几个终端,每个终端都有自己配置环境变量的命令。
临时环境变量设置:*
在powershell中,使用
$env
来设置和查看环境变量,powershell关闭后,改命令创建的环境变量就销毁了。在CMD和Cmder中,使用
set
来设置和查看环境变量,同样,也是临时的。持久化环境变量设置:
Windows设置持久化的环境变量有两种方式:
第一种(fnm和corepack不推荐):是经典的环境变量窗口设置,直接win键按出菜单搜索“环境变量”,大家根据图中路径打开窗口。可以看到这里有两块区域,分别对应用户级和系统级的环境变量。直接新建并输入变量名和值即可。
但是这里的环境变量通常是一些常用生产程序的路径,我们将fnm、corepack或者其他一些程序的环境变量放这里,会很显得很杂乱,不好管理,因此推荐下面的类似Linux/Mac的方式。

第二种(推荐):在Windows中创建一个类似Linux中的启动脚本文件,当终端一打开,就自动设置临时环境变量,也相当于持久化了。powershell、cmd、cmder设置各有不同,下面一一来看。
powershell:powershell的配置简单,直接终端输入命令
notepad $profile
会用记事本打开一个C:\Users\UserName\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
文件。你可以在里面写入命令,一行一个命令,打开powershell前,回先依次执行这些命令。cmder:cmder的启动脚本文件在
%CMDER_ROOT%\config\user_profile.cmd
%CMDER也是个环境变量,记录了一个路径,可以在环境变量设置窗口中找到。配置cmd太麻烦了,如果不是非要用cmd,建议只配置powershell吧。
cmd(系统级):我们得先修改注册表(为什么要改注册表?)。注册表和环境变量很类似,也是一些键值对,供程序读取使用,这里不展开赘述。搜索"注册表编辑器",并进入图中位置。空白处右击,新建一个字符串值。然后填入
值名称:AutoRun,数值数据:xxx/xxx/xxx.cmd
这里的值数据填一个路径,指向一个.bat结尾的文件。然后你在这个位置创建这个.bat文件,这就是cmd的启动脚本文件,你可以在里面写命令,每次打开cmd都会执行。
上述方式会作用到整个系统,也就是所有用户打开cmd都会尝试执行这个脚本(如果脚本文件不存在可能报错,未验证)。
cdm(用户级):要想设置到用户级,我们可以到下图所示的注册表路径,也就是
HKEY_CURRENT_USER
下面,一看名字就和用户有关。路径和系统级的配置差不多,但是,你会发现Microsoft下没有Command Processor?没事,可以自己创建一个,右击Microsoft文件夹(这个文件夹一样的东西在注册表里叫“项”)。然后把新项重命名为Command Processor。之后的操作就和上面一样了,添加AutoRun键值对,建立启动脚本文件,写入命令。

4.4 再探 fnm env
有了环境变量相关的知识,我们就能完全理解fnm env工作过程了。
由于我用的Windows系统,所以我们使用powershell和cmd各自运行
fnm env
命令,结果如下:
powershell结果如下:cmd结果如下:
我们可以发现,这不就是powershell和cmd各自用来设置环境变量的命令嘛!
我们还可以发现,同样一句
fnm env
,fnm根据不同的终端,输出了与之对应的命令!但是,这些命令被输出到终端里了,并没有真正的执行,比如我们想fnm每次下载node后开启corepack,输入
fnm env --corepack-enabled
,可以看到powershell输出下列内容:
这里相关环境变量显示未true,但是当我们输入
$env: FNM_COREPACK_ENABLED
后,发现这个值还是默认的false。
因此,fnm env 的真正作用,只是输出这些设置环境变量的命令的字符串,但是得靠我们自己来执行。

再回头看看fnm文档中配置shell的部分,我们可以学习到,如何执行这些命令:


Linux中可以使用
eval "$()"
命令,将fnm env输出的字符串替换掉$(),这样就可以用eval来执行这些命令了,--shell bash 参数,又保证了输出的是针对bash的命令。
powershell中同理,也是利用终端本身执行字符串数据的能力,通过管道操作,把fnm输出的流用Out-String处理为字符串,再用管道输送给Invoke-Expression,Invoke-Expression就能执行这些命令。
把这些命令写入启动脚本文件,就完成了启动终端立马进行环境变量初始化的操作。4.5 corepack的环境变量
corepack没有给出设置环境变量的命令,因此我们直接在启动脚本文件中设置对应的环境变量即可,按着文档来。
五、疑难杂症
5.1 网络问题
我们使用fnm下载node或者使用corepack下载包管理器,可能会出现timeout超时错误,排除自身网络原因,最大的可能就是与海外链接不畅。
如果你是魔法师,请配置代理:
fnm: fnm直接使用系统代理,读取系统代理的环境变量,大家可以自行查阅相关环境变量:
如果你是麻瓜,可以将下载源改为国内的镜像源:
fnm: 使用
fnm env --node-dist-mirror 镜像源地址
可以获取换源的命令。当然也可以直接设置FNM_NODE_DIST_MIRROR
环境变量,它的默认值是https://nodejs.org/dist
。反正你已经知道环境变量怎么配了,哪种方法都可以。
corepack: corepack的下载源地址用环境变量COREPACK_NPM_REGISTRY
来配置。默认是https://registry.npmjs.org
。5.2 corepack下载的包管理器在哪里?
默认在:C:\Users\username\AppData\Local\node\corepack\v1

长期收录中。。。