记一次解决 Node 版本不一致的问题

· 778 words · 4 min

我很喜欢 VSCode 提供的 .vscode/tasks.json 来快捷运行 npm script 的功能,在发现这个问题之前,一切正常无事发生。

// .vscode/tasks.json
{
	"version": "2.0.0",
	"tasks": [
		{
			"type": "npm",
			"script": "dev:uat",
			"problemMatcher": [],
			"label": "npm: dev:uat",
			"detail": "cross-env BUILD_ENV=uat MODE=uat node build/dev.js"
		}
	]
}

在 VSCode 中使用 Cmd+R 唤起任务弹窗,选择任务然后运行。

VSCode task config

任务运行成功后终端显示如下。

Task run successful

直到我开发一个老项目,该项目使用 webpack 打包,只支持 node 16。我在终端使用命令 n 16 切换 node 版本后运行 yarn dev:uat 没有任何问题。 然后我配置了 .vscode/tasks.json,使用任务来跑脚本的时候终端报错如下。

Task failed

我明明切换了 node 版本,用 node -v 看一下终端的 node 版本是正确的。

Node version

当我百思不得其解的时候,我给 npm script 加上了 which node 来看一下 task 执行的时候读取 node 的位置。

VSCode Node location

从 task output 中可以看到打印出的 node location 是一串非常奇怪的地址,在将注意力集中于这个地址之前,我尝试看了 VSCode 文档的关于 task 部分的内容, 通过 task 的 options.env 等配置了 NODE_VERSION、NODE_PATH 以及 $PTAH 等变量,发现仍然无效。

正当我实在没办法,想把这个奇怪的路径放到浏览器去搜一下的时候,浏览器识别出了是一个文件,帮我加上了 file:// 协议,结果神奇的现象发生了。

file protocol

我恍然大悟,原来这是一个可执行文件,内容是使用这个地址的 node 去执行后面的 $@,$@ 表示跟在脚本后面的所有参数。

# "$@" 即为 "npm run dev:uat"
exec "/usr/local/bin/node" "npm run dev:uat"
# 也等价于
exec "/usr/local/bin/node" "cross-env BUILD_ENV=uat MODE=uat node build/dev.js"

原来 VSCode 内部默认的 node location 是 /usr/local/bin/node ,因此查看了一下终端 的 node location 发现和 VSCode 的 node location 不一致。

Terminal Node location

为什么 n 安装的 node location 是这个呢?突然想起来,在安装 n 的时候,根据官方文档的说明,我改过 node 安装地址。

N installation

我查看了一下我的 ~/.zshrc 配置文件,其中包含了 N_PREFIX 的配置内容。

# set n
export N_PREFIX="$HOME/.n"
export PATH="$N_PREFIX/bin:$PATH"

所以导致这个问题出现的大致原因浮出了水面:

  1. 配置了 N_PREFIX 导致了 全局的 node location 是 /Users/captainofphb/.n/bin/node
  2. VSCode 内部的 node 脚本读取的 node location 是固定的 /usr/local/bin/node
  3. 因此无论怎么切换 node version,VSCode 的 task 都访问不到我想要的 node 版本,因为 $PATH 的顺序是 /Users/captainofphb/.n/bin 在前

让我们 echo $PATH 看一下为什么终端的 node 版本是对的:

echo $path

要解决这个问题,需要把 n 安装的 node location 默认为全局,删掉 N_PREFIX。按照 n 官方文档部分运行了相关命令之后使用 sudo n 16 来安装 node 16。

sudo n 16

再次查看一下 node version 和 node location。

Check Node version again

重新运行了一下 VSCode 的 task ,发现一切恢复了正常。

Finally worked!
Node
Tricks
Debug