案发:

最近遇到个问题,当你jenkins服务器上运维因为各种原因不愿意装nvm或者n等版本控制升级node而系统默认版本一直是超低版本的node。想指定node运行版本怎么办呢?

之前大佬们遗留的jenkins脚本是这样写得:

从一个bug开始,3分种搞清楚npm run发生了什么_npm run

再看看run build的script是怎么写的:

从一个bug开始,3分种搞清楚npm run发生了什么_npm run_02

然后喜闻乐见,打包无限失败:

从一个bug开始,3分种搞清楚npm run发生了什么_npm run_03

查了一下说是node版本问题,但看上去没问题啊,已经是node-v12了,跟本地的node版本一致啊,那究竟怎么办呢,本地打包直接发布,让我带你们一步一步解开谜题

疑云

乍一看没问题,通过服务器上绝对路径启动指定版本npm运行srcipt脚本,但是,当我们把build:test加一个"node -v"就会发现,

从一个bug开始,3分种搞清楚npm run发生了什么_npm run_04

这是怎么回事呢,为什么我指定了npm版本,node却是系统的v8.x呢?但事实就是这样,小编也感到非常惊讶。

线索

随后小编就查一下npm run的相关资料,发现这样两句话:

In addition to the shell's pre-existing PATH, npm run adds node_modules/.bin to the PATH provided to scripts. Any binaries provided by locally-installed dependencies can be used without the node_modules/.bin prefix. The actual shell your script is run within is platform dependent. By default, on Unix-like systems it is the /bin/sh command, on Windows it is the cmd.exe. The actual shell referred to by /bin/sh also depends on the system. As of npm@5.1.0 you can customize the shell with the script-shell configuration.

原来在你执行script的时候,会自动将“node_modules/.bin”作为前缀,查找到你这条命令对应的脚本,比如vue-cli-service对应的是“node_modules/.bin/vue-cli-service”然后根据平台环境通过不同的默认shell执行脚本。并不是在启动npm当时的那个shell中执行。

破案

翻译一下在服务端输入“/usr/local/node-v12.9.1-linux-x64/bin/npm run build:test”用这段话打包的时候会发生什么,就很清楚了

  1. 使用node-12自带的npm模块执行run build:test
  2. build:test对应的脚本即"cross-env CUSTOM_ENV=test vue-cli-service build"
  3. 从一个bug开始,3分种搞清楚npm run发生了什么_npm run_05从一个bug开始,3分种搞清楚npm run发生了什么_npm run_06
  4. 通过系统默认shell(未指定时)执行脚本。
  5. 以vue-cli为例,sh的脚本长这样:从一个bug开始,3分种搞清楚npm run发生了什么_npm run_07
  6. vue-cli的打包脚本是怎么跑的因为篇幅原因我就不多讲了,这不属于我的知识范畴本文内容。

解决

但看懂了这段,应该对怎么解决有了很多办法:

  • 可以自己写个.sh的脚本,Jenkins的bash中的直接执行该脚本,同样以vue-cli-serve脚本中的一行为例,比如:将node "$basedir/../@vue/cli-service/bin/vue-cli-service.js" "$@"改为/usr/local/node-v12.9.1-linux-x64/bin/node "$basedir/../node_modules/@vue/cli-service/bin/vue-cli-service.js" "$@",注意添加node_modules即可

    从一个bug开始,3分种搞清楚npm run发生了什么_npm run_08从一个bug开始,3分种搞清楚npm run发生了什么_npm run_09

  • 可以在script中直接写死,Jenkins执行shell不变,直接npm run build:test:

     "scripts": {  "build:test": "cross-env CUSTOM_ENV=test /usr/local/node-v12.9.1-linux-x64/bin/node 'node_modules/@vue/cli-service/bin/vue-cli-service.js' build",
     },复制代码
  • 拉着运维的手求他装个nvm/n不装不让办公