npm 与 cnpm 打包踩坑小记

本文最后更新于:2022年7月6日 上午

有的时候掉头发就是这么简单。。。

故事就这么长

大家都知道,使用 npm scripts 运行命令  的时候,是可以用 process.env.npm_config_argv 来获取命令行参数的,尤其是存在多环境的时候。

npm run build --test6

当我们运行上述命令的时候,我们可以打印一下此时的 process.env.npm_config_argv

'{"remain":[],"cooked":["run","build:test","--test6"],"original":["run","build:test","--test6"]}'

没错,它的值是一个字符串,因此我们可以先解析一下再取对应的环境变量:

// 读取命令行参数确实是哪个 test 环境
const configArgv = JSON.parse(process.env.npm_config_argv).original;
console.log(configArgv);

// 打印结果
// ["run", "build:test", "--test6"]

一看这是个数组阿,数组第三项就是我们需要的环境信息,简直完美,撸袖子干起来:

// 读取命令行参数确实是哪个 test 环境
const configArgv = JSON.parse(process.env.npm_config_argv).original;
const argv = configArgv[2];
const env = argv.substring(2);

齐活了,获取到环境变量信息了。打包、测试、发布一套带走。这样一直用了半年多,没出过什么问题,直到。。。。

公司开搞 k8s 之后,所有项目的打包、发布都要在 Rancher 上操作了,经过运维人员一顿犀利操作之后,我们惊喜的发现打包出现问题了。

问题就是每次打的包都是线上包,也就是说打包的时候没有获取到环境变量信息,所以就默认打成线上包了。

经过定位之后发现,部署到 k8s 后,使用的是 cnpm 命令打包,而 cnpm 获取到的命令行参数与 npm 有一些不同的地方:

// 读取命令行参数确实是哪个 test 环境
const configArgv = JSON.parse(process.env.npm_config_argv).original;
console.log(configArgv);

// 打印结果
// ["run", "build:test", ..., ..., "--test6"]

中间的省略号就不表了,闹心,总之我们取数组的第三项肯定不是环境信息了。

但是我们可以发现 cnpmnpm 二者的命令行参数有个共同的地方:环境变量都在数组最后一项,于是我们可以这样:

// 读取命令行参数确实是哪个 test 环境
const configArgv = JSON.parse(process.env.npm_config_argv).original;
const argv = configArgv.pop(); // 取最后一项
const env = argv.substring(2);

现在又完美啦。。。

结尾

现在看来,这个问题并不大,也很好排查。只是在特定时间、特定地点的时候,一个小 bug 也会让你焦头烂额,只能慢慢经历了呗。


 目录