今天有开发的同事问我说,在本机开发的 windows 上运行构建命令报错,不知道怎么回事儿。
作为一名 Mac 用户,当然也不知道为什么啦,过去看看,果然有错误。
我们的开发构建命令是基于 npm
的 scripts
,其实就是很简单的一句话:
{ "scripts": { ... "build": "NODE_ENV=production webpack --progress --hide-modules" }, ... }
这个命令在 Mac 下没有问题,在 windows 下运行却报如下错误:
0 info it worked if it ends with ok 1 verbose cli [ 'C://Program Files//nodejs//node.exe', 1 verbose cli 'C://Program Files//nodejs//node_modules//npm//bin//npm-cli.js', 1 verbose cli 'run', 1 verbose cli 'build' ] 2 info using npm@3.10.8 3 info using node@v6.9.1 4 verbose run-script [ 'prebuild', 'build', 'postbuild' ] 5 info lifecycle @~prebuild: @ 6 silly lifecycle @~prebuild: no script for prebuild, continuing 7 info lifecycle @~build: @ 8 verbose lifecycle @~build: unsafe-perm in lifecycle true 9 verbose lifecycle @~build: PATH: C:/Program Files/nodejs/node_modules/npm/bin/node-gyp-bin;<WORK_DIR>/node_modules/.bin;C:/Users/<USER_DIR>/bin;F:/Git/mingw64/bin;F:/Git/usr/local/bin;F:/Git/usr/bin;F:/Git/usr/bin;F:/Git/mingw64/bin;F:/Git/usr/bin;C:/Users/<USER_DIR>/bin;C:/Windows/system32;C:/Windows;C:/Windows/System32/Wbem;C:/Windows/System32/WindowsPowerShell/v1.0;C:/Program Files (x86)/NVIDIA Corporation/PhysX/Common;C:/Program Files/nodejs;C:/Go/bin;C:/Users/<USER_DIR>/AppData/Local/Microsoft/WindowsApps;C:/Users/<USER_DIR>/AppData/Roaming/npm;F:/Git/usr/bin/vendor_perl;F:/Git/usr/bin/core_perl 10 verbose lifecycle @~build: CWD: <WORK_DIR> 11 silly lifecycle @~build: Args: [ '/d /s /c', 11 silly lifecycle 'NODE_ENV=production webpack --progress --hide-modules' ] 12 silly lifecycle @~build: Returned: code: 1 signal: null 13 info lifecycle @~build: Failed to exec build script 14 verbose stack Error: @ build: `NODE_ENV=production webpack --progress --hide-modules` 14 verbose stack Exit status 1 14 verbose stack at EventEmitter.<anonymous> (C:/Program Files/nodejs/node_modules/npm/lib/utils/lifecycle.js:255:16) 14 verbose stack at emitTwo (events.js:106:13) 14 verbose stack at EventEmitter.emit (events.js:191:7) 14 verbose stack at ChildProcess.<anonymous> (C:/Program Files/nodejs/node_modules/npm/lib/utils/spawn.js:40:14) 14 verbose stack at emitTwo (events.js:106:13) 14 verbose stack at ChildProcess.emit (events.js:191:7) 14 verbose stack at maybeClose (internal/child_process.js:877:16) 14 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:226:5) 15 verbose pkgid @ 16 verbose cwd <WORK_DIR> 17 error Windows_NT 10.0.14393 18 error argv "C://Program Files//nodejs//node.exe" "C://Program Files//nodejs//node_modules//npm//bin//npm-cli.js" "run" "build" 19 error node v6.9.1 20 error npm v3.10.8 21 error code ELIFECYCLE 22 error @ build: `NODE_ENV=production webpack --progress --hide-modules` 22 error Exit status 1 23 error Failed at the @ build script 'NODE_ENV=production webpack --progress --hide-modules'. 23 error Make sure you have the latest version of node.js and npm installed. 23 error If you do, this is most likely a problem with the package, 23 error not with npm itself. 23 error Tell the author that this fails on your system: 23 error NODE_ENV=production webpack --progress --hide-modules 23 error You can get information on how to open an issue for this project with: 23 error npm bugs 23 error Or if that isn't available, you can get their info via: 23 error npm owner ls 23 error There is likely additional logging output above. 24 verbose exit [ 1, true ]
调试了一下,问题就出在这个命令本身。
这位同学开发用的是 git-shell 自带的命令行,本身是支持 linux 命令执行的。
比如我们直接在命令行下执行:
NODE_ENV=production export NODE_ENV=production
都是没问题的,但结合到 npm scripts 上,却运行失败。
当我们去掉这个 env 设定,再次执行 npm scripts 命令:
{ "scripts": { ... "build": "webpack --progress --hide-modules" }, ... }
就会发现没问题了,但结果当然是不是我们想要的。
怎么办?
可以把要执行的代码写到独立的 JS 中,使用 node 命令来运行,比如:
{ "scripts": { ... "build": "node build/build.js" }, ... }
在 build/build.js
文件中,再设定执行环境之类的:
var ora = require('ora') var webpack = require('webpack') var webpackConfig = require('../webpack.config.js') process.env.NODE_ENV = 'production' var spinner = ora('building for production...') spinner.start() webpack(webpackConfig, function (err, stats) { spinner.stop() if (err) throw err process.stdout.write(stats.toString({ colors: true, modules: false, children: false, chunks: false, chunkModules: false }) + '/n') })
这其实也是 vue
脚手架自动生成的构建方式,果然还是最佳实践靠谱一点。