关于
微信公众号:前端呼啦圈(Love-FED)
个人博客:劳卜的博客
知乎专栏:前端呼啦圈
前言
先前写了一篇webpack入门的文章《webpack入门必知必会》,简单介绍了webpack拆分、打包、压缩的使用方法。本文将在上篇文章的基础上进一步讲解在使用webpack构建的项目中存在的优化方案与解决方法。javascript
上篇文章中写了一份webpack最基本的配置文件来打包压缩咱们的代码:html
var path = require('path');
module.exports = {
entry: './app/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
}复制代码
在入口文件index.js中咱们引入了jQuery:前端
// index.js
var $ = require('jquery');
var str = require('./hello.js');
function main(){
$('body').html(str);
}
main();复制代码
这样咱们虽然可以实现代码的统一打包,将jQuery、index.js、hello.js通通打包到了bundle.js里,可是会存在一个问题:每次打包都会生成一个体积较大的新bundle.js,浏览器没法缓存像jQuery这样的基本不会改动的框架库代码文件,影响加载速度。java
发现问题咱们就来解决问题,咱们最终但愿的是将像jQuery这样的框架库代码与项目自身的代码分开打包,生成一个独立的打包文件,缩减单个文件体积,浏览器也不用每次都进行加载。jquery
步骤
1.独立打包
为了解决上述问题,咱们须要修改咱们的webpack配置文件:webpack
var webpack = require('webpack');
var path = require('path');
module.exports = {
entry: {
main: './app/index.js',
vendor: ['jquery']
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
},
plugins:[
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor'
}),
]
}复制代码
上方咱们将本来的单入口文件改为了多入口文件,并加入了vendor属性。vendor属性用于配置打包第三方类库,写入数组的类库名将统一打包到一个文件里。git
同时咱们将输出的filename用[name]变量来自动生成文件名,最后咱们添加了一个CommonsChunkPlugin的插件,用于提取vendor。github
配置完成后咱们运行webpack命令:web
Hash: ee1daf95c1986768927a
Version: webpack 2.3.2
Time: 573ms
Asset Size Chunks Chunk Names
main.js 340 bytes 0 [emitted] main
vendor.js 274 kB 1 [emitted] [big] vendor
[0] ./~/jquery/dist/jquery.js 267 kB {1} [built]
[1] ./app/hello.js 53 bytes {0} [built]
[2] ./app/index.js 114 bytes {0} [built]
[3] multi jquery 28 bytes {1} [built]复制代码
最终发现咱们成功将jQuery打包到了vendor.js中,实现了独立打包,可是问题又来了:每次打包后生成的文件名都是同样的,浏览器可能缓存上一次的结果而没法加载最新数据。npm
2.添加hash
为了解决上述问题,咱们须要为打包后的文件名添加hash值,这样每次修改后打包的文件hash值将改变,修改配置文件以下:
module.exports = {
...
output: {
filename: '[name].[chunkHash:5].js',
path: path.resolve(__dirname, 'dist')
},
...
}复制代码
上方咱们在输出文件名中增长了[chunkHash:5]变量,表示打包后的文件中加入保留5位的hash值。咱们再次运行打包命令:
Hash: c7d1295f2f9a27c412d2
Version: webpack 2.3.2
Time: 603ms
Asset Size Chunks Chunk Names
main.2a7ad.js 337 bytes 0 [emitted] main
vendor.49eb4.js 274 kB 1 [emitted] [big] vendor
[0] ./~/jquery/dist/jquery.js 267 kB {1} [built]
[1] ./app/hello.js 50 bytes {0} [built]
[2] ./app/index.js 114 bytes {0} [built]
[3] multi jquery 28 bytes {1} [built]复制代码
上方咱们发现打包后的文件成功加上了hash值,这样每次修改文件后hash值也会跟着变,就不怕浏览器缓存了,可是当咱们尝试去修改一个js文件后再次打包,问题又来了:vendor.js的hash值也变了,咱们并无修改jQuery的源码。
3.修改vendor配置
上述问题产生的缘由是由于CommonsChunkPlugin插件是用于提取公共代码的,上方咱们只是提取了vendor做为公共代码。为了继续解决上述问题,其实方法很简单,咱们须要修改CommonsChunkPlugin的配置,以下:
module.exports = {
...
plugins:[
new webpack.optimize.CommonsChunkPlugin({
names: ['vendor', 'manifest']
}),
]
...
}复制代码
如此咱们修改一下hello.js中的代码,发现vendor的hash值并未改变,而且多了一个manifest.js的小文件。manifest.js为webpack的启动文件代码,它会直接影响到hash值,用mainfest单独抽出来了,这样vendor的hash就不会变了。
4.生成index.html
经过以上对webpack配置文件的一系列修改,咱们成功实现了webpack的独立打包与缓存处理,可是还差最后一步。
由于咱们最终打包后生成的文件名中带有hash值,每次都是会变的,因此咱们不能像目前这样在index.html中写死路径。
index.html
...
...复制代码
以上写法是不对的,由于缺乏了可变的hash值,所以咱们但愿每次打包后index.html中的路径也会自动加上hash值,解决方法以下:
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
...
plugins:[
...
new HtmlWebpackPlugin({
title: 'demo',
template: 'index.html' // 模板路径
}),
...
]
...
}复制代码
上方咱们引入了html-webpack-plugin这一个插件,该插件能够帮助咱们根据模板生成html文件。在plugins设置中,title配置了生成html中的title部分,template为模板html的路径地址。
咱们须要下载html-webpack-plugin:
npm install html-webpack-plugin --save-dev复制代码
安装和配置完毕后,运行打包命令:webpack
Hash: 0c4b91e206579b31544d
Version: webpack 2.3.2
Time: 856ms
Asset Size Chunks Chunk Names
vendor.e1868.js 268 kB 0 [emitted] [big] vendor
main.44412.js 337 bytes 1 [emitted] main
manifest.ed186.js 5.81 kB 2 [emitted] manifest
index.html 292 bytes [emitted]
[0] ./~/jquery/dist/jquery.js 267 kB {0} [built]
[1] ./app/hello.js 50 bytes {1} [built]
[2] ./app/index.js 114 bytes {1} [built]
[3] multi jquery 28 bytes {0} [built]复制代码
咱们发如今dist目录下生成了一个index.html文件,打开该文件后代码以下:
demo复制代码
至此咱们实现了每次打包后index.html中的路径也会自动加上hash值的功能,所以dist目录下的index.html即为之后的首页文件,最后咱们在浏览器中打开该文件成功显示:
结语
本文在webpack入门的基础上讲解了webpack独立打包与缓存处理的方式,实例代码已上传个人github,地址为:github.com/luozhihao/w…, 供参考。
若是以为本文对你有帮助,能够关注个人微信公众号,来这里聊点关于前端的事情。