· 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 唤起任务弹窗,选择任务然后运行。
任务运行成功后终端显示如下。
直到我开发一个老项目,该项目使用 webpack 打包,只支持 node 16。我在终端使用命令 n 16
切换 node 版本后运行 yarn dev:uat
没有任何问题。
然后我配置了 .vscode/tasks.json,使用任务来跑脚本的时候终端报错如下。
我明明切换了 node 版本,用 node -v
看一下终端的 node 版本是正确的。
当我百思不得其解的时候,我给 npm script 加上了 which node
来看一下 task 执行的时候读取 node 的位置。
从 task output 中可以看到打印出的 node location 是一串非常奇怪的地址,在将注意力集中于这个地址之前,我尝试看了 VSCode 文档的关于 task 部分的内容, 通过 task 的 options.env 等配置了 NODE_VERSION、NODE_PATH 以及 $PTAH 等变量,发现仍然无效。
正当我实在没办法,想把这个奇怪的路径放到浏览器去搜一下的时候,浏览器识别出了是一个文件,帮我加上了 file://
协议,结果神奇的现象发生了。
我恍然大悟,原来这是一个可执行文件,内容是使用这个地址的 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 不一致。
为什么 n 安装的 node location 是这个呢?突然想起来,在安装 n 的时候,根据官方文档的说明,我改过 node 安装地址。
我查看了一下我的 ~/.zshrc 配置文件,其中包含了 N_PREFIX 的配置内容。
# set n
export N_PREFIX="$HOME/.n"
export PATH="$N_PREFIX/bin:$PATH"
所以导致这个问题出现的大致原因浮出了水面:
/Users/captainofphb/.n/bin/node
/usr/local/bin/node
/Users/captainofphb/.n/bin
在前让我们 echo $PATH
看一下为什么终端的 node 版本是对的:
要解决这个问题,需要把 n 安装的 node location 默认为全局,删掉 N_PREFIX。按照 n 官方文档部分运行了相关命令之后使用 sudo n 16
来安装 node 16。
再次查看一下 node version 和 node location。
重新运行了一下 VSCode 的 task ,发现一切恢复了正常。