续 前端临床手札——webpack构建逐步解构(上)
工作流程
案例:multiple-page-vue-webpack-example
最近添加了雪碧图功能,并把sass-loader
替换成postcss
的press
,详细可以看分支develop
构建生产
上一篇说完了本地测试webpack
和express
是如何工作,接下来分析构建生产模式下webpack
配置如何配置和每个模块干了什么。
从流程能看到,这里用到两个模块build.js
和webpack
。当你进入build.js
文件能看到没干什么,其实这里可以理解为构建生产代码前的预处理部分(删除已构建的文件、拷贝静态资源相关的操作等),实际工作还是webpack
完成的。
因此接下来说明的内容就剩下webpack
配置了,打开webpack.prod.conf.js能看到前面设置也没什么大变化,但是添加的plugins
却有点不同。
webpackConfig.plugins = [].concat(webpackConfig.plugins, utils.htmlLoaders(config.template, webpackConfig.entry), [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
// https://github.com/glenjamin/webpack-hot-middleware#installation--usage
// new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.OccurrenceOrderPlugin(),
new ExtractTextPlugin(utils.assetsPath('css/[name].[contenthash:5].css')),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
// TODO: set node_modules fallback
minChunks: function (module, count) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
chunks: ['vendor']
})
])
utils.htmlLoaders()
上一篇说过了是多入口页面的设置,剩下的分别有:
webpack.optimize.UglifyJsPlugin()
webpack.optimize.OccurrenceOrderPlugin()
ExtractTextPlugin()
webpack.optimize.CommonsChunkPlugin()
接下来一个个讲解,首先是webpack.optimize.UglifyJsPlugin
webpack.optimize.UglifyJsPlugin
从名字能看出他是负责压缩处理js的,其他没啥好说的细节请看官方说明
webpack.optimize.OccurrenceOrderPlugin
这个看官方文档说明感觉是个处理分包的机制的插件,然而也没啥好说的了。
ExtractTextPlugin
这个插件用来合并css文件,除了最后压缩调用外,前面在所有输出css的配置也得使用上ExtractTextPlugin.extract()
来提前提取css配置。由于封装到utils.js
的cssLoaders
方法下,这里代码并没有体现出来。
webpack.optimize.CommonsChunkPlugin
这个得重点说一说,webpack
厉害之处在于他分包的科学计算法的体现就是这个插件,能智能地帮你把代码拆分成多个包而已加载时并没依赖缺失,下面讲解配置,你也可以看官方文档
使用
new webpack.optimize.CommonsChunkPlugin(options)
配置说明
options.name
合并或拆分后的名字,多用于设置。options.filename
这个当然是指生成出来的文件名字options.chunks
指定js代码块来进行处理,默认使用的是入口文件及其依赖options.children
这个具体有什么用博主还真没搞懂options.async
设置为true,就可以创建一个异步请求的代码块options.minSize
创建一个公共块之前的模块的最小尺寸,意思就是小于这个大小的块并不会合并options.minChunks
最小分割成多少个代码块,设置为Infinity
就不会进行合并代码。除此之外还可以设置方法,自己写合并规则,想案例就是这样处理的。
从案例分析,每个CommonsChunkPlugin将会是生成一个代码块,下面这段是生成一个入口公共块,同时必须在html-webpack-plugin
的依赖添加上(参考文档utils.js)
webpack.prod.conf.js
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
chunks: ['vendor']
})
utils.js
Object.keys(pages).forEach(function(pathname) {
let conf = {
filename: path.normalize(pages[pathname][0].replace(template.replace(/\*\*.*$/,''),'')), //生成的html存放路径,相对于path
template: pages[pathname][0], //html模板路径
inject: false, //js插入的位置,true/'head'/'body'/false
};
if (pathname in webpackEntry) {
conf.inject = 'body';
conf.chunks = ['manifest','vendor', pathname];
conf.hash = true;
conf.chunksSortMode='dependency';
}
plugins.push(new HtmlWebpackPlugin(conf));
});
而下面这段,则是将node_modules
目录下任何所需的模块提取到vendor.js
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
// TODO: set node_modules fallback
minChunks: function (module, count) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
})
最后
到这里估计对webpack
配置的比较迷惑的同学已经清晰了多少,然而这篇并不是从头帮你解析webpack所有配置的文章,内容和标题货不对板有点抱歉,却还是希望不懂的人自己多看官方文档,官方文档很多时候已经说得比较清楚。我自己也是经常使用一些插件时懵逼了去google找其他人使用的帮助,然而半天没找到比较靠谱的方法,最后还是反复啃官方文档或者看源码解决的。所以或许这篇文章不能真正解决你的疑惑,但愿能很好地教会你看官方文档;)。
然后在写完这篇文章后,发现webpack还是有些功能需要gulp补充的,比如css的压缩、图片的处理(雪碧图、svg等),希望最近能有空补上这块内容吧!