上一篇文章写了vue反向代理,这篇文章紧接后续。
遇见bug
项目开发完成后,前端人员一般需要打包部署上线,而我在打包的时候出现了一个问题,导致打包不成功,后面发现是webpack的DefinePlugin插件问题,其实也是我对webpack不了解,没有按照插件要求格式写,出现的问题,今天有空,记录一下
分析bug
- 先来看看报错语句提示
- 打开static/js/31.5a6c80708b85cf7e1939.js文件,ctrl+g跳转到88:6600这个代码位置,
- 发现这里已经被压缩了,这个地方就是我这上一篇文章中写的prod.env.js写的代理地址,这里写的有问题吗?看一下打包前的样子
'use strict'
module.exports = {
NODE_ENV: '"production"',
API_HOST: "http://172.16.4.238:14022",//生产环境中加上这段关键,不然出错
}
- prod.env.js打包前貌似没有什么问题,只是那个production使用了两个引号有点奇怪,应该也没什么问题,再来看看上面那张打包后的图,箭头位置前面一点,production打包后只有一个引号了,http地址一个引号都没有了,从字符串变成了变量。咦,为什么会这么奇怪呢?难道这里会默认去掉一对引号?试着把http地址也加上两对引号,果然打包成功了。
bug回顾
既然是打包的时候出现的问题,那就从执行npm run build 的时候开始看
- 先看package.json文件
{
...
"scripts": {
"d": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev || --host 0.0.0.0",
"b": "node build/build.js",
"dev": "node config/dev.js",
"build": "node config/build.js"
},
...
}
- 这个项目这打包(npm run b)的时候执行build.js,再看看build.js有什么
'use strict'
require('./check-versions')()
process.env.NODE_ENV = 'production'
const ora = require('ora')
const rm = require('rimraf')
const path = require('path')
const chalk = require('chalk')
const webpack = require('webpack')
const config = require('../config')
const webpackConfig = require('./webpack.prod.conf')
const spinner = ora('building for production...')
spinner.start()
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, (err, stats) => {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
chunks: false,
chunkModules: false
}) + '\n\n')
if (stats.hasErrors()) {
console.log(chalk.red(' Build failed with errors.\n'))
process.exit(1)
}
console.log(chalk.cyan(' Build complete.\n'))
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})
})
- build.js里面先是声明了环境,然后引入了一些模块,主要运用的代码时webpack,那就看看build.js里面webpack相关的东西,关于webpack,build.js引入了webpack.prod.conf.js文件,再去到webpack.prod.conf.js文件看看
-
webpack.prod.conf.js文件里面引入了prod.env.js文件,在下面的DefinePlugin插件里面使用了,bug的真相终于要浮出水面了。
-
从执行打包命令 npm run b 开始,执行 build.js ---> webpack.prod.conf.js ---> prod.env.js,前面都是引入文件,不会也不应有什么问题,唯一有问题的地方那就是这一块,终于锁定bug位置了
- 那这个DefinePlugin又是什么呢?直接翻阅webpack官方文档,找到DefinePlugin,看一遍,不是很明白,但是官网写了为什么要加两个引号,再去百度搜DefinePlugin,看了好几篇文章,终于是弄明白了。
bug产生原因解释
-
DefinePlugin在编译的时候会生成一个全局变量,在编译的时候,将变量对应的值直接替换到代码中,如果只写一个引号,取到的值就是一个未定义变量,写了两个引号就是一个字符串。
-
之前在DefinePlugin里面定义了一个对象
new webpack.DefinePlugin({
'process.env': env
}),
- 那么就会在全局有一个process.env对象
process.env = {
NODE_ENV: '"production"',
API_HOST: '"http://172.16.4.238:14022"',//生产环境中加上这段关键,不然出错
}
- 在后面文件使用时出现问题
process.env.NODE_ENV === 'production' ? true : false
- DefinePlugin插件使用后就变成了这样,一个变量production与一个字符串"production"进行比较,就出现了问题,http地址那里同理,所以需要使用两个引号,来保证我们拿到的值始终为正确格式。
production === 'production' ? true : false