前言
先前寫了一篇webpack入門的文章《webpack入門必知必會(huì)》俄认,簡單介紹了webpack拆分、打包、壓縮的使用方法典尾。本文將在上篇文章的基礎(chǔ)上進(jìn)一步講解在使用webpack構(gòu)建的項(xiàng)目中存在的優(yōu)化方案與解決方法。
上篇文章中寫了一份webpack最基本的配置文件來打包壓縮我們的代碼:
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();
這樣我們雖然能夠?qū)崿F(xiàn)代碼的統(tǒng)一打包河闰,將jQuery褥紫、index.js、hello.js統(tǒng)統(tǒng)打包到了bundle.js里髓考,但是會(huì)存在一個(gè)問題:每次打包都會(huì)生成一個(gè)體積較大的新bundle.js,瀏覽器無法緩存像jQuery這樣的基本不會(huì)改動(dòng)的框架庫代碼文件儡炼,影響加載速度查蓉。
發(fā)現(xiàn)問題我們就來解決問題,我們最終希望的是將像jQuery這樣的框架庫代碼與項(xiàng)目自身的代碼分開打包豌研,生成一個(gè)獨(dú)立的打包文件,縮減單個(gè)文件體積鬼佣,瀏覽器也不用每次都進(jìn)行加載霜浴。
步驟
1.獨(dú)立打包
為了解決上述問題,我們需要修改我們的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屬性用于配置打包第三方類庫翁狐,寫入數(shù)組的類庫名將統(tǒng)一打包到一個(gè)文件里。
同時(shí)我們將輸出的filename用[name]變量來自動(dòng)生成文件名露懒,最后我們添加了一個(gè)CommonsChunkPlugin的插件砂心,用于提取vendor。
配置完成后我們運(yùn)行webpack命令:
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]
最終發(fā)現(xiàn)我們成功將jQuery打包到了vendor.js中坎弯,實(shí)現(xiàn)了獨(dú)立打包译暂,但是問題又來了:每次打包后生成的文件名都是一樣的,瀏覽器可能緩存上一次的結(jié)果而無法加載最新數(shù)據(jù)崎脉。
2.添加hash
為了解決上述問題,我們需要為打包后的文件名添加hash值伯顶,這樣每次修改后打包的文件hash值將改變,修改配置文件如下:
module.exports = {
...
output: {
filename: '[name].[chunkHash:5].js',
path: path.resolve(__dirname, 'dist')
},
...
}
上方我們在輸出文件名中增加了[chunkHash:5]變量啦撮,表示打包后的文件中加入保留5位的hash值汪厨。我們再次運(yùn)行打包命令:
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]
上方我們發(fā)現(xiàn)打包后的文件成功加上了hash值赃春,這樣每次修改文件后hash值也會(huì)跟著變劫乱,就不怕瀏覽器緩存了,但是當(dāng)我們嘗試去修改一個(gè)js文件后再次打包狭吼,問題又來了:vendor.js的hash值也變了殖妇,我們并沒有修改jQuery的源碼。
3.修改vendor配置
上述問題產(chǎn)生的原因是因?yàn)镃ommonsChunkPlugin插件是用于提取公共代碼的,上方我們只是提取了vendor作為公共代碼疲吸。為了繼續(xù)解決上述問題摘悴,其實(shí)方法很簡單,我們需要修改CommonsChunkPlugin的配置蹂喻,如下:
module.exports = {
...
plugins:[
new webpack.optimize.CommonsChunkPlugin({
names: ['vendor', 'manifest']
}),
]
...
}
如此我們修改一下hello.js中的代碼葱椭,發(fā)現(xiàn)vendor的hash值并未改變口四,并且多了一個(gè)manifest.js的小文件蔓彩。manifest.js為webpack的啟動(dòng)文件代碼,它會(huì)直接影響到hash值粪小,用mainfest單獨(dú)抽出來了抡句,這樣vendor的hash就不會(huì)變了。
4.生成index.html
通過以上對(duì)webpack配置文件的一系列修改待榔,我們成功實(shí)現(xiàn)了webpack的獨(dú)立打包與緩存處理锐锣,但是還差最后一步。
因?yàn)槲覀冏罱K打包后生成的文件名中帶有hash值姿骏,每次都是會(huì)變的斤彼,所以我們不能像目前這樣在index.html中寫死路徑。
index.html
...
<body>
<script src="./dist/main.js"></script>
<script src="./dist/vendor.js"></script>
<script src="./dist/manifest.js"></script>
</body>
...
以上寫法是不對(duì)的嘲玫,因?yàn)槿鄙倭丝勺兊膆ash值并扇,因此我們希望每次打包后index.html中的路徑也會(huì)自動(dòng)加上hash值,解決方法如下:
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
...
plugins:[
...
new HtmlWebpackPlugin({
title: 'demo',
template: 'index.html' // 模板路徑
}),
...
]
...
}
上方我們引入了html-webpack-plugin這一個(gè)插件土陪,該插件可以幫助我們根據(jù)模板生成html文件旺坠。在plugins設(shè)置中,title配置了生成html中的title部分取刃,template為模板html的路徑地址璧疗。
我們需要下載html-webpack-plugin:
npm install html-webpack-plugin --save-dev
安裝和配置完畢后崩侠,運(yùn)行打包命令: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]
我們發(fā)現(xiàn)在dist目錄下生成了一個(gè)index.html文件漆魔,打開該文件后代碼如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>demo</title>
</head>
<body>
<script type="text/javascript" src="manifest.ed186.js"></script>
<script type="text/javascript" src="vendor.e1868.js"></script>
<script type="text/javascript" src="main.44412.js"></script>
</body>
</html>
至此我們實(shí)現(xiàn)了每次打包后index.html中的路徑也會(huì)自動(dòng)加上hash值的功能改抡,因此dist目錄下的index.html即為以后的首頁文件阿纤,最后我們在瀏覽器中打開該文件成功顯示:
結(jié)語
本文在webpack入門的基礎(chǔ)上講解了webpack獨(dú)立打包與緩存處理的方式,實(shí)例代碼已上傳我的github藐窄,地址為:https://github.com/luozhihao/webpack-course/tree/master/vendor荆忍, 供參考东揣。