臨近春節(jié),公司很多同事都提前回家過年,剩余人員根據(jù)禪道去修改bug,當(dāng)bug修正完畢以后,我們需要重新打包給運(yùn)維,上測(cè)試服給測(cè)試同事提測(cè),但是由于項(xiàng)目本體比較龐大,所以打包時(shí)間太過漫長(二十五分鐘以上:sob:),所以有了打包優(yōu)化的想法(其實(shí)想法早就有了,但是因?yàn)槠綍r(shí)工作計(jì)劃比較充實(shí),所以一直沒有去完成這個(gè)工作),這次正好有時(shí)間,所以去重新考慮了這個(gè)問題!
webpack是react項(xiàng)目標(biāo)配的打包工具,和NPM搭配起來使用管理模塊實(shí)在非常方便。
webapck 把所有的靜態(tài)資源都看做是一個(gè) module,通過 webpack,將這些 module 組成到一個(gè) bundle 中去,從而實(shí)現(xiàn)在頁面上引入一個(gè) bundle.js,來實(shí)現(xiàn)所有靜態(tài)資源的加載。
話不多說,直接開始正文吧
先給大家看一下項(xiàng)目的目錄結(jié)構(gòu):
就是正常的項(xiàng)目結(jié)構(gòu),簡單說一下吧:
優(yōu)化思路
項(xiàng)目打包時(shí)間長,原因無外乎就是項(xiàng)目整體比較龐大、依賴復(fù)雜、組件之前拆分不夠合理。
對(duì)于這三個(gè)問題呢,我們可以針對(duì)下面這幾個(gè)方面去做一下處理:
實(shí)際操作
有了整體的思路,那么開搞就可以啦 去webpack文檔去看了一下有一個(gè)DllPlugin,這個(gè)插件就是幫助我們解決問題的關(guān)鍵,下面是我webpack.dll.config的代碼:
var path = require("path");var webpack = require("webpack");function resolve (dir) { return path.join(__dirname, '..', dir)}module.exports = { // 你想要打包的模塊的數(shù)組 entry: { vendor: ['vue', 'lodash', 'vuex', 'axios', 'vue-router', 'iview', 'element-ui', 'echarts','xlsx','jquery','vue-fullcalendar','vue-cookie','handsontable'] }, output: { path: path.join(__dirname, '../dist/vendor-dll-js'), // 打包后文件輸出的位置 filename: '[name].dll.js', library: '[name]_library' // vendor.dll.js中暴露出的全局變量名。 // 主要是給DllPlugin中的name使用, // 故這里需要和webpack.DllPlugin中的`name: '[name]_library',`保持一致。 }, resolve: { extensions: ['.js', '.vue', '.json'], alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src'), } }, plugins: [ new webpack.DllPlugin({ path: path.join(__dirname, '.', '[name]-manifest.json'), name: '[name]_library', context: __dirname }), // 壓縮打包的文件,與該文章主線無關(guān) new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }) ]};我們需要將項(xiàng)目中具有重用性的包抽離出來,放在vendor數(shù)組里面,然后在下面output里面定義一下打包輸出的文件路徑,然后在resolve里面配置解析參數(shù),最后定義使用的DllPlugin插件,UglifyJsPlugin是壓縮js的插件
Dllplugin里的path,會(huì)輸出一個(gè)vendor-manifest.json,這是用來做關(guān)聯(lián)id的,打包的時(shí)候不會(huì)打包進(jìn)去,所以不用放到static里 然后運(yùn)行一下 webpack -p --progress --config build/webpack.dll.conf.js
成功以后,static下會(huì)有dll.vendor.js,根目錄下會(huì)有vendor.manifest.json 各自打開看一下,就會(huì)看到依賴庫的源碼和匹配id
ok,到這里,抽離依賴庫的事情就完成了,那么接下來問題就是怎么引用呢,怎么在dev和build跑呢?
這里補(bǔ)了一點(diǎn)dll和commonsChunk概念上的區(qū)別,commonsChunk之所以慢和大,是因?yàn)槊看蝦un的時(shí)候,都會(huì)去做一次打包,而實(shí)際上我們不會(huì)一直去更新我們引用的依賴庫,所以dll的做法就等于是,事先先打包好依賴庫,然后只對(duì)每次都修改的js做打包。
繼續(xù)上面的步驟,我們需要根據(jù)生成的json文件去修改webpack.base.config文件:
const manifest = require('../vendor-manifest.json')......plugins: [ new webpack.DllReferencePlugin({ manifest }) ]然后打開index.html,在底部加上 <script src="./static/dll.vendor.js"></script> ;
執(zhí)行一下 npm run build ,一起正常的話,表示你的操作是正確的。
升級(jí)處理
至此優(yōu)化的問題基本已經(jīng)解決了,但是在處理過程中需要進(jìn)行復(fù)制粘貼,還要對(duì)index.html文件進(jìn)行操作,如果是對(duì)于項(xiàng)目不熟悉的人來進(jìn)行開發(fā)項(xiàng)目的話,就會(huì)出現(xiàn)一些小的問題,所以我決定繼續(xù)往下研究一下:
思路還是上面的思路,我們下面需要進(jìn)行的操作呢就是對(duì)與之前的處理進(jìn)行優(yōu)化,通過配置文件,和命令去實(shí)現(xiàn)我們想要的效果
首先我們將上面 webpack.dll.config 文件里面的entry配置項(xiàng)拿出來,在config文件夾下新建一個(gè)dll.js
module.exports = { entry: { // 這里的依賴順序必須是:對(duì)象從上往下依賴,數(shù)組從右到左依賴(如果互不依賴的可以忽略順序) ui: ['iview', 'element-ui'], tool: ['lodash', 'jquery', 'axios', 'vue-fullcalendar'], vue: ['vue', 'vuex', 'vue-router', 'vue-cookie'], xlsx: ['xlsx'], echarts: ['echarts'], other: ['handsontable'], }, outFile: '../static/dll'};這里面其實(shí)就是我們一開始寫的entry的配置項(xiàng),根據(jù)這個(gè)js去打包的文件有一個(gè)順序,就是我總結(jié)的這個(gè):
這里的依賴順序必須是:對(duì)象從上往下依賴,數(shù)組從右到左依賴(如果互不依賴的可以忽略順序)
如果不按照這個(gè)順序去寫的話,會(huì)出現(xiàn)依賴錯(cuò)誤的問題!!!
然后在output里面再進(jìn)行一下配置:
output: { path: path.join(__dirname, dllConfig.outFile), // 打包后文件輸出的位置 filename: '[name].dll.[chunkhash].js', library: '[name]_library' // 主要是給DllPlugin中的name使用, // 故這里需要和webpack.DllPlugin中的`name: '[name]_library',`保持一致。 },這樣在執(zhí)行 webpack -p --progress --config build/webpack.dll.conf.js 指令的時(shí)候會(huì)生成如下:
是不是看到文件后面的hash就一臉懵逼,這怎么辦,我們沒有辦法去進(jìn)行復(fù)制粘貼了?。。ㄎ覀兊哪康牟痪褪遣贿M(jìn)行復(fù)制粘貼嗎 正經(jīng)臉-_-)
要實(shí)現(xiàn)命令操作之后不進(jìn)行復(fù)制粘貼操作就需要使用webpack的HtmlWebpackPlugin插件
在plugins里面配置一下HtmlWebpackPlugin
new HtmlWebpackPlugin({ filename: path.join(__dirname, '../', config.dev.index), template: 'index.ejs', inject: false}),然后在根目錄添加一個(gè)index.ejs模版(ejsGitHub地址 ), index.ejs中代碼如下:
<body> <div id="app"></div> <!-- dll files will be auto injected --> <% for (var chunk in htmlWebpackPlugin.files.chunks) { %><script type="text/javascript" src="/<%= htmlWebpackPlugin.files.chunks[chunk].entry %>"></script> <% } %> <!-- built files will be auto injected --></body>最后需要在config文件夾下的index.js進(jìn)行一下修改: 在dev中添加: index: 'index.html',
項(xiàng)目在執(zhí)行dev指令或者build指令之前需要先執(zhí)行: webpack -p --progress --config build/webpack.dll.conf.js 在dll指令結(jié)束后 執(zhí)行其他操作就可以完美的玩耍了:blush:
總結(jié)
至此代碼打包優(yōu)化的整個(gè)過程就基本結(jié)束了,測(cè)試一下,15分鐘左右就可以完成打包,比之前打包快了將近10分鐘,可以說是非常成功的一次嘗試??!
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注