当执行了npm run dev
命令来编译前端资源时,经常会遇到一个报错,类似这样:
> [email protected] dev /home/vagrant/Code
> cross-env NODE_ENV=development webpack --progress --hide-modules
sh: 1: cross-env: not found
npm ERR! Linux 4.4.0-51-generic
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "run" "dev"
npm ERR! node v7.8.0
npm ERR! npm v4.2.0
npm ERR! file sh
npm ERR! code ELIFECYCLE
npm ERR! errno ENOENT
npm ERR! syscall spawn
npm ERR! [email protected] dev: `cross-env NODE_ENV=development webpack --progress --hide-modules`
npm ERR! spawn ENOENT
或者说:
npm ERR! Failed at the @ dev script 'cross-env NODE_ENV=development webpack --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js'.
可能你具体的错误提示还稍有差异,不过这里先不管它,重点在于问题是出在cross-env
这个组件上。
这个cross-env
是个什么鬼?有什么用?
Most Windows command prompts will choke when you set environment variables with NODE_ENV=production like that. (The exception is Bash on Windows, which uses native Bash.) Similarly, there's a difference in how windows and POSIX commands utilize environment variables. With POSIX, you use: $ENV_VAR and on windows you use %ENV_VAR%.
好吧,又是微软Windows的锅~也即是我们在windows系统上使用NODE_ENV=production
这样的方式来设置node
环境时,因为windows的系统变量是%ENV_VAR%
这种格式,而“行业标准”是$ENV_VAR
这样的,当然windows上的bash例外。
那么为了解决这个跨平台环境变量的问题,就有了cross-env
这个组件。知道这些个有啥用呢?
用处是,cross-env
只是用在windows系统上的,在Mac和Linux系统上没用,不需要装,装了反而会坏事儿~
所以从这一点上,你的问题其实有两种可能:
- 你的项目环境是Windows系统,你没有装
cross-env
,或者说因为路径等其他原因调用不到它。 - 你的项目环境是Linux或Mac,这个时候你没必要装
cross-env
,但是你却装了,或者说laravel默认带了,而且装就装吧,路径调用往往还有错 - 这里特别的是,如果你是用的Homestead开发环境,因为你虚拟机里是Linux,所以如果你在Host主机上去操作,那你就是Windows环境,如果你
vagrant ssh
进了虚拟机操作,那么就是Linux环境;
所以解决办法也要基于你的项目开发环境:
一、 Linux(Homestead)或Mac环境下:
你要做的,只是将你的package.json
文件中的cross-env
删掉即可:
"dev": "node NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch": "node NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch-poll": "node NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --watch-poll --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"hot": "node NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
"production": "node NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
二、 Windows系统下(WAMP、MAMP)
- 首先你需要装一下
cross-env
,执行:
npm install --save-dev cross-env --no-bin-links
或者你也可以全局安装一下cross-env
,以防止以后在其他项目也出现类似错误:
npm install -g cross-env --no-bin-links
- 将
package.json
文件中的cross-env
调用换成具体路径node_modules/cross-env/dist/bin/cross-env.js
,最终类似这样:
"dev": "node node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch": "node node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch-poll": "node node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --watch-poll --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"hot": "node node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
"production": "node node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
- 保险起见,再执行一下
npm install --no-bin-links
- 然后再去执行
npm run dev
来试试
为什么会出来这么多梗?甚至很多人因此诟病laravel 5.4不友好——直接下载全新安装都跑不起来
因为一直到laravel 5.4.15,laravel的package.json是这样的:
{
"private": true,
"scripts": {
"dev": "node node_modules/cross-env/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch": "node node_modules/cross-env/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch-poll": "node node_modules/cross-env/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --watch-poll --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"hot": "node node_modules/cross-env/bin/cross-env.js NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
"production": "node node_modules/cross-env/bin/cross-env.js NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},
"devDependencies": {
"axios": "^0.15.3",
"bootstrap-sass": "^3.3.7",
"jquery": "^3.1.1",
"laravel-mix": "^0.8.1",
"lodash": "^4.17.4",
"vue": "^2.1.10"
}
}
可以看到它的devDependencies
里没有依赖cross-env
,但是在上方声明了cross-env
的路径:node_modules/cross-env/bin/cross-env.js
,因为laravel-mix
这个组件里用到了cross-env
。但是没多久,cross-env
的作者对组件路径做了更改,将cross-env/bin
换成了cross-env/dist
,于是在这个laravel commit里,package.json文件里更改了cross-env
的路径,同时"devDependencies"里加上了"cross-env": "^3.2.3"
,然后没几天,作者们意识到既然依赖了cross-env,就没必要上面写具体路径了,所以在这个laravel commit里,package.json文件变成这样:
{
"private": true,
"scripts": {
"dev": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch-poll": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --watch-poll --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},
"devDependencies": {
"axios": "^0.15.3",
"bootstrap-sass": "^3.3.7",
"cross-env": "^3.2.3",
"jquery": "^3.1.1",
"laravel-mix": "^0.8.1",
"lodash": "^4.17.4",
"vue": "^2.1.10"
}
}
这期间呢,laravel-mix的作者Jeffway看到laravel里依赖了cross-env,所以他就在laravel-mix里直接取消了对cross-env的依赖,因为没必要重复安装,这直接导致了一系列问题的发生。而且这期间,laravel里对cross-env的依赖一直停留在"cross-env": "^3.2.3",直到5.4.30,才突然变成"cross-env": "^5.0.1"
. 所以呢,取决于你所使用的laravel和laravel-mix的版本,可能是你package.json里没有cross-env而报错,也可能是路径变了以后没更新,也可能是laravel调用的版本一直太低,因为这期间你可能执行了composer update
或npm update
这些命令而导致两者的小版本都发生变化,所以说不清道不明的问题就发生了。