require返回Object带来的线上bug
更新日期:
2015-10-28 400上线 entry.biz.{hash}.js 404
背景:
400系统测试环境http://192.168.1.224:8080/internal/index.html; 线上 http://400.zufangzi.com;
400第一版上线后,首页加载js太大,速度慢,进行优化后,部分js——entry.biz.{hash}.js ,会在登陆后,点击菜单进行加载。
按需加载的js,在测试环境js的路径是 xx /internal/asset, 线上是 asset/。因此,webpack线上的config中publicPath设置为了/asset/, 测试环境是/internal/asset/,测试环境测试通过。
case:
2015-10-27晚上上线后,没有登陆,进行检查,FE也没有跟进上线。2015-10-28 发现400登陆后,菜单点击无效。排查问题后,发现 entry.biz.{hash}.js的请求路径不对,线上应该是 http://400.zufangzi.com/asset/entry.biz.{hash}.js,但是却是 http://400.zufangzi.com/internal/asset/entry.biz.{hash}.js;
原因:
线上webpack的配置文件:wp.config.release.js
var webpack = require("webpack");
var config = require('./wp.config')
var ExtractTextPlugin = require('extract-text-webpack-plugin');
// 线上
config.output.publicPath = '/asset/';
......
module.exports = config;
测试环境的配置文件:wp.config.staging.js
var webpack = require("webpack");
var config = require('./wp.config')
var ExtractTextPlugin = require('extract-text-webpack-plugin');
config.output.publicPath = "/internal/asset/";
......
module.exports = config;
公共的wp.config.js
module.exports = {
entry: {
common: ['react', 'antd'],
entry: [
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/only-dev-server',
'./src/router'
]
},
debug: true,
// devtool: 'cheap-module-inline-source-map',
output: {
// @NOTE: https://github.com/webpack/webpack-dev-server/issues/88
// use to solve the proble which path is unvalid
path: '/',
publicPath: '/asset/',
filename: '[name].js',
chunkFilename: 'entry.biz.[hash].js'
},
module: {
....
},
......
}
由上面的代码可知配置文件,的确是没有问题的。
gulp打包线上代码:
import gutil from 'gulp-util';
import webpack from 'webpack';
import {exec} from 'child_process';
import definePlugin from './util/define-plugin.js';
// create optimizations array
const optimizations = [
definePlugin,
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin({
output: {
comments: false,
},
compress: {
warnings: false,
},
}),
];
// get build config
const buildConfig = require('../buildConfig.js');
// get webpack config
const wpConfig = buildConfig.webpackConfig.production;
// export initilizer
export default (gulp) => {
gulp.task('build', function(callback) {
......
});
};
由上可知,gulp引入的文件,也没有问题。
查看 buildConfig.js, 问题出在以下代码的3个require
export default {
webpackConfig: {
debug: require('./wp.config.js'),
production: require('./wp.config.release.js'),
staging: require('./wp.config.staging.js')
},
devServer: {
// settings for dev-server
// @link: https://github.com/webpack/webpack-dev-server/pull/127
proxy: [
],
headers: {
}
}
};
require的机制是,require一个文件时,先解析出这个文件的路径,读取文件,然后将该文件丢如一个context运行,获取和保存exports,当其他地方,再次require这个文件时,会将之前保存的exports直接返回给你。
由wp.config.js 的代码可知,wp.config.js exports出的是个Object。
所以,在buildConfig.js代码片段中:production:require(‘./wp.config.release.js’)—— wp.config.release.js中require了wp.config.js, 并且将publicPath 改为了/asset/; 在staging: require(‘./wp.config.staging.js’) 中—— wp.config.staging.js再次require了wp.config.js,其实,它们拿到的是同一个Object,并将publicPath 改为了/internal/asset/;
因此,虽然走的是线上的编译配置文件,但是publicPath还是测试环境的。