您的位置:首页 > Web前端 > Webpack

webpack优化不完全指南

2018-01-14 15:13 295 查看

基础篇

最基本的一个webpack配置

const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
entry: __dirname + "/app/main.js", //已多次提及的唯一入口文件
output: {
path: __dirname + "/build",
filename: "bundle-[hash].js"
},
devtool: 'none',
devServer: {
contentBase: "./public", //本地服务器所加载的页面所在的目录
historyApiFallback: true, //不跳转
inline: true,
hot: true
},
module: {
rules: [{
test: /(\.jsx|\.js)$/,
use: {
loader: "babel-loader"
}
}, {
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: [{
loader: "css-loader",
options: {
modules: true,
localIdentName: '[name]__[local]--[hash:base64:5]'
}
}, {
loader: "postcss-loader"
}],
})
}
}
]
},
plugins: [
new webpack.BannerPlugin(),
new HtmlWebpackPlugin({
template: __dirname + "/app/index.tmpl.html" //new 一个这个插件的实例,并传入相关的参数
}),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin(),
new ExtractTextPlugin("style.css")
]
};

接下来基于这份配置进行一个优化:

首先我们得区分开发环境、生产环境以及测试环境(这个在国内用的公司少)实现思路(参考vue-cil),通用配置可以设置一个base文件然后exports,在其他的配置文件中require进来。

上面这个配置中new webpack.optimize.UglifyJsPlugin()就可以放入webpack.prod.conf.js中,因为代码压缩丑化只需要在生产环境中使用,在开发过程开启的话,不仅编译时间加长还不利于调试。

module与entry、output这个就可以放到webpack.base.cong.js文件中,这些配置是通用的不管在生产环境还是开发环境中都是用得到的。

devServer则是在开发过程中需要启动一个服务器然后再开启热替换功能。

在module中也可进行些优化,例如在后缀为.js文件的处理中添加:

include: [resolve('src'), resolve('test')]

这样loader加载器就只会匹配src/与/test目录下的文件,至于node_modules目录下的文件则跳过,假如没加这一限制条件的话,node_modules下那么多的js文件,想想都觉得恐怖,并且别人发布出来的包文件一般都是经过babel转成ES5标准的。

添加alias,如:

alias: {

'@': resolve('src')

}

这样当webpack遇到import('@xxx')的时候就会直接在src/目录下去寻找,能节省不少的目录查询时间

进阶篇

多页面优化

当我们的项目是多个页面的时候,我们需要用到HtmlWebpackPlugin插件,

for(let i = 0; i< html.length; i++) {
plugins.push(
new HtmlWebpackPlugin({
filename:fileName,
template: path.join('./src/html/', fileName),
inject: true,
minify: {
removeComments: true,
collapseWhitespace: false,
removeAttributeQuotes: true
},
chunksSortMode: 'dependency',
chunks: ['manifest', 'vendor', cur]
}))
)
}

有多少个页面就push多少个HtmlWebpackPlugin进去,至于页面的获取我们可以通过walk-sync来做到,通过获取目录下的入口文件来判断有多少个页面存在。

我在优化过程中遇到个坑,当webpack从2.x升级为3.x的时候,

compilation.getStats().toJson()

这个函数的执行时间会大大加长,我看到其实在issue里头有人提出来了,不过作者并没有给合并到master中去。还有点就是:当页面是多页面的时候每一次小的改动都会把所有的html文件重新生成一次,针对这两个优化我在Githubfork了下html-webpack-plugin,并发布了html-webpack-plugin-multihtml。我们的项目一共是有49个页面之前rebuild是花费5-7s ,优化后保持在1s左右。

提取公共代码CommonsChunkPlugin

有些类库如utils, bootstrap之类的可能被多个页面共享,最好是可以合并成一个js,而非每个js单独去引用。这样能够节省一些空间。这时我们可以用到CommonsChunkPlugin,我们指定好生成文件的名字,以及想抽取哪些入口js文件的公共代码,webpack就会自动帮我们合并好。

new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
chunks: Object.keys(entrys),
minChunks: function (module, count) {
return (module.resource && /\.js$/.test(module.resource) && module.resource.indexOf(path.join(__dirname, '../node_modules')) === 0 && count > 8)
}
}),

这个是针对多页面优化的,CommonsChunkPlugin会自己计算当一个类库被引用的次数超过8次,就把它打包至vendor中,这样就不必全打包至一个index.js里头

externals提取常用库

externals 配置选项提供了「从输出的 bundle 中排除依赖」的方法。相反,所创建的 bundle 依赖于那些存在于用户环境(consumer's environment)中的依赖。

externals主要是防止将某些import的包打包到bundle中,而是在运行时(runtime)再去从外部获取这些扩展依赖

配置也挺简单的接下来贴下代码:

index.html中引入

<script src="https://code.jquery.com/jquery-3.1.0.js"></script>

webpack.config.js中配置

externals: {
jquery: 'jQuery'
}

这样就能在代码中通过import引用了:

import $ from 'jquery';

uglifyPlugin多线程压缩代码

在webpack的默认情况下,都是单线程跑的,有个叫webpack-uglify-parallel的插件,它能够充分调用计算机的资源,利用计算机的多核特性进行代码压缩。

使用方法也挺简单的,把之前webpack.prod.conf.js中的

new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
drop_console: true
},
comments: false
}),

替换为

var os = require('os');
var UglifyJsParallelPlugin = require('webpack-uglify-parallel');

module.exports = {
/// ... rest of config
plugins: [
new UglifyJsParallelPlugin({
workers: os.cpus().length, // usually having as many workers as cpu cores gives good results
// other uglify options
})
]
}

即可GitHub地址:webpack-uglify-parallel

Happypack

happypack 是 webpack 的一个插件,目的是通过多进程模型,来加速代码构建。目前我们项目中已经配置并且上线了,效果还可以,从最初的40s减少到30s的编译时间。

配置按照GitHub上的来,也不难

var HappyPack = require('happypack');
var happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });

// 省略其余配置
module: {
loaders: [
{
test: /\.less$/,
loader: ExtractTextPlugin.extract('style',path.resolve(__dirname,'./node_modules', 'happypack/loader') + '?id=less'
)
}
]
},
plugins: [
new HappyPack({
id: 'less',
loaders: ['css!less'],
threadPool: happyThreadPool,
cache: true,
verbose: true
})
]

我在优化我们项目的webpack遇到了两个坑,一个就是上面提到的,webpack2升级3编译时间增多,另一个就是devServer在低版本安卓机型上跑步起来。devServer这个使用"webpack-dev-server": "2.7.1"即可,因为2.9.x版本使用的是es6的写法安卓4.1以下不支持,ie9以下也不支持。

作者:Zore_

链接:https://juejin.im/post/5a49fb696fb9a0451e402718

来源:掘金

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: