詳解基于DllPlugin和DllReferencePlugin的webpack構(gòu)建優(yōu)化
一個(gè)基于vue-cli webpack2模板創(chuàng)建的項(xiàng)目.項(xiàng)目中使用到了vue+vue-router+axios+muse-ui+iview
現(xiàn)在構(gòu)建一次需要的時(shí)間大概是40s左右.真心受不了.雖然在開(kāi)發(fā)過(guò)程中,我們不太需要關(guān)心構(gòu)建時(shí)間.但是如果在開(kāi)發(fā)hybridApp時(shí),構(gòu)建的次數(shù)就會(huì)增多.
一般我們可以把項(xiàng)目分為三部分.
分類(lèi) | 說(shuō)明 | 變動(dòng)頻率 |
---|---|---|
vendor_library | 核心庫(kù) | 低 |
vendor | 一般項(xiàng)目依賴(lài) | 中等 |
code | 業(yè)務(wù)邏輯 | 高 |
vendor_library:比如vue,vue-router,axios 這些變動(dòng)頻率極低的文件可以利用 DllPlugin 和 DllReferencePlugin 進(jìn)行預(yù)編譯.
vendor,code在開(kāi)發(fā)階段,每次構(gòu)建都需要編譯.但是一旦完成該次開(kāi)發(fā)任務(wù),應(yīng)該調(diào)整vendor 是否加入vendor_library.
BundleAnalyzerPlugin 的插件使用
BundleAnalyzerPlugin 是分析 Webpack 生成的包體組成并且以可視化的方式反饋給開(kāi)發(fā)者的插件。
vue已經(jīng)默認(rèn)集成了該插件. 如果你運(yùn)行 npm run build –report.就能看到當(dāng)前項(xiàng)目的依賴(lài)情況.然后做出相應(yīng)調(diào)整.
優(yōu)化方向
按需加載
muse-ui,iview 都提供了按需加載的方式,按照文檔調(diào)整即可.
分類(lèi) | 耗時(shí) | muse-ui | iview |
---|---|---|---|
before | 13256ms | 234KB | 337KB |
after | 43211ms | 79KB | 75KB |
先看結(jié)果...你沒(méi)看錯(cuò),'優(yōu)化后',時(shí)間竟然變長(zhǎng)了...😂.不過(guò)這也正常,之前的依賴(lài)直接獲取的是dist目錄的文件,現(xiàn)在需要在src目錄下獲取.增加了編譯的過(guò)程.
但是文件大小的減少還是喜人的.當(dāng)然,這取決于項(xiàng)目中對(duì)模塊的使用程度.在我們這個(gè)項(xiàng)目中iview只使用了的四個(gè)控件.結(jié)果上看,顯然還是按需加載比較劃算.不過(guò)這個(gè)不算是時(shí)間上的優(yōu)化,只是因?yàn)閐ll可以解決構(gòu)建時(shí)間問(wèn)題,使按需加載變的更好用.
DllPlugin 和 DllReferencePlugin 預(yù)編譯資源模塊
Dll這個(gè)概念應(yīng)該是借鑒了Windows系統(tǒng)的dll。一個(gè)dll包,就是一個(gè)純純的依賴(lài)庫(kù),它本身不能運(yùn)行,是用來(lái)給你的app引用的。
打包dll的時(shí)候,Webpack會(huì)將所有包含的庫(kù)做一個(gè)索引,寫(xiě)在一個(gè)manifest文件中,而引用dll的代碼(dll user)在打包的時(shí)候,只需要讀取這個(gè)manifest文件,就可以了。
這么一來(lái)有幾個(gè)好處:
Dll打包以后是獨(dú)立存在的,只要其包含的庫(kù)沒(méi)有增減、升級(jí),hash也不會(huì)變化,因此線(xiàn)上的dll代碼不需要隨著版本發(fā)布頻繁更新。
App部分代碼修改后,只需要編譯app部分的代碼,dll部分,只要包含的庫(kù)沒(méi)有增減、升級(jí),就不需要重新打包。這樣也大大提高了每次編譯的速度。
假設(shè)你有多個(gè)項(xiàng)目,使用了相同的一些依賴(lài)庫(kù),它們就可以共用一個(gè)dll。
網(wǎng)上抄的… 其實(shí)意思就是我們可以把項(xiàng)目的公共模塊,基本不會(huì)改動(dòng)的模塊.想我們剛才說(shuō)的定義為vendor_library的內(nèi)容,進(jìn)行預(yù)編譯編譯.以后在項(xiàng)目構(gòu)建過(guò)程中,vendor_library部分直接引用,就不需要再編譯了.
這也是為什么按需加載可以得到更好的使用,正常構(gòu)建流程,因?yàn)槭褂昧税葱杓虞d,會(huì)導(dǎo)致每次的構(gòu)建都比使用全量加載用時(shí)要長(zhǎng).而使用dll,核心庫(kù)只需要編譯一次,以后直接引用即可.
先來(lái)看一下改進(jìn)結(jié)果:
分類(lèi) | 耗時(shí) |
---|---|
before | 57192ms |
after | 7890ms |
哈哈,有沒(méi)有快到飛起!?。?/p>
DllPlugin 和 DllReferencePlugin 使用
新建webpack.dll.conf.js文件
//webpack.dll.conf.js process.env.NODE_ENV = 'production' const path = require('path'); var utils = require('./utils') var vueLoaderConfig = require('./vue-loader.conf') var ExtractTextPlugin = require('extract-text-webpack-plugin') var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') const webpack = require('webpack'); //vue項(xiàng)目默認(rèn)有一個(gè)static目錄.我就把導(dǎo)出目錄放在了static/dll/目錄下 const srcPath = path.join(__dirname, '../static/dll/'); //需要編譯的模塊 const vendors = ['vue/dist/vue.esm.js', 'vue-router', 'vue-localstorage', 'material-design-icons/iconfont/material-icons.css', 'iview/dist/styles/iview.css', 'iview/src/components/tag/tag.vue' 'muse-ui/src/appBar' ]; webpackConfig = { entry: { vendor: vendors }, resolve: { extensions: ['.js', '.vue', '.json'] }, module: { loaders: [ { test: /\.vue$/, loader: 'vue-loader', options: vueLoaderConfig }, { test: /iview.src.*?js$/, loader: 'babel-loader' }, { test: /muse-ui.src.*?js$/, loader: 'babel-loader' }, { test: /\.css$/, use: ExtractTextPlugin.extract({ use: "css-loader" }) }, { test: /\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/, loader: 'url-loader', options: { publicPath: './', limit: 1000, name: 'fonts/[name].[ext]' } }] }, output: { path: srcPath, // 輸出的路徑 filename: '[name].dll.js', // 輸出的文件,將會(huì)根據(jù)entry命名為vendor.dll.js library: '[name]_library' // 暴露出的全局變量名 }, plugins: [ new ExtractTextPlugin({ filename: '[name].dll.css' }), new OptimizeCSSPlugin({ cssProcessorOptions: { safe: true } }), new webpack.optimize.UglifyJsPlugin({ // uglifjs壓縮 compress: { warnings: false } }), new webpack.DllPlugin({ path: path.join(srcPath, '[name]-mainfest.json'), // 描述依賴(lài)對(duì)應(yīng)關(guān)系的json文件 name: '[name]_library', context: __dirname // 執(zhí)行的上下文環(huán)境,對(duì)之后DllReferencePlugin有用 }) ] } if (process.env.npm_config_report) { var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin webpackConfig.plugins.push(new BundleAnalyzerPlugin()) } module.exports = webpackConfig;
其實(shí)這就是一個(gè)正常的構(gòu)建文件.根據(jù)你的項(xiàng)目進(jìn)行修改即可.唯一不同的是在plugins多了一個(gè)DllPlugin.他會(huì)生成一個(gè)描述依賴(lài)對(duì)應(yīng)關(guān)系的json文件.
static目錄如下:
|____dll | |____fonts | |____vendor-mainfest.json | |____vendor.dll.css | |____vendor.dll.js
修改模板index.html 根據(jù)你的構(gòu)建結(jié)果做修改.
//head 標(biāo)簽 <link type="text/css" rel="stylesheet" href="./static/dll/vendor.dll.css" rel="external nofollow" > //body 標(biāo)簽 <script src="./static/dll/vendor.dll.js"></script>
修改webpack.base.conf.js
plugins: [ ..., new webpack.DllReferencePlugin({ context: __dirname, manifest: require('../static/dll/vendor-mainfest.json') // 指向生成的json文件 }) ]
執(zhí)行
webpack --config ./build/webpack.dll.conf.js
你也可以將該語(yǔ)句放入npm run 中.'build:dll:report' 是為了優(yōu)化dll依賴(lài)關(guān)系,添加的另外一條命令.上文已經(jīng)提過(guò),我們可以借用BundleAnalyzerPlugin插件查看當(dāng)前包的依賴(lài)情況,和包體組成情況.
//package.json "scripts":{ "build:dll": "webpack --config ./build/webpack.dll.conf.js", "build:dll:report": "npm run build:dll --report" }
npm run build
…看看這次的構(gòu)建時(shí)間吧
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
微信登錄過(guò)程、openId、token詳解(代碼實(shí)現(xiàn))
這篇文章主要介紹了微信登錄過(guò)程、openId、token詳解,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-08-08js實(shí)現(xiàn)按Ctrl+Enter發(fā)送效果
按Ctrl+Enter發(fā)送,思路是監(jiān)聽(tīng)textarea的onkeydown事件,當(dāng)ctrl鍵被按下,并且,keycode為13(回車(chē)),時(shí),調(diào)用發(fā)送表單的函數(shù)2014-09-09js中用window.open()打開(kāi)多個(gè)窗口的name問(wèn)題
這篇文章主要介紹了js中用window.open()打開(kāi)多個(gè)窗口的問(wèn)題,需要的朋友可以參考下2014-03-03關(guān)于AOP在JS中的實(shí)現(xiàn)與應(yīng)用詳解
這篇文章主要給大家介紹了關(guān)于AOP在JS中的實(shí)現(xiàn)與應(yīng)用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用JS具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05微信小程序開(kāi)發(fā)之左右分欄效果的實(shí)例代碼
本文以一個(gè)簡(jiǎn)單的小例子,簡(jiǎn)述在微信小程序開(kāi)發(fā)中左右分欄功能的實(shí)現(xiàn)方式,主要涉及scroll-view ,列表數(shù)據(jù)綁定,及簡(jiǎn)單樣式等內(nèi)容,感興趣的朋友跟隨小編一起看看吧2019-05-05