本文主要介紹兩個插件的使用,DllPlugin 和 DllReferencePlugin,後者配合前者使用。css
項目 Github 地址:https://github.com/luxiancan/vue-permission-managehtml
打包會輸出一個類 dll 包(dll 包源於 windows 的動態連接庫),這些代碼自己不會執行,主要是提供給咱們的業務代碼引用。(好比 dll 中有一個工具方法爲獲取本月日期數組,這個方法自己並不會執行,可是當咱們的業務中須要獲取本月日期時,就會引用這個方法在咱們的業務中執行相關邏輯)。vue
DllPlugin 能夠將特定的類庫提早打包而後引入。這種方式能夠極大的減小打包類庫的次數,只有當類庫更新版本纔有須要從新打包,而且也實現了將公共代碼抽離成單獨文件的優化方案。node
簡單來講就是:
將靜態資源文件(運行依賴包)與業務代碼源文件分開打包,先使用 DllPlugin 給靜態資源打包,再使用 DllReferencePlugin 讓源文件引用資源文件。webpack
當咱們一個項目引入了多個較大的包之後,這些包自己並不會運行,咱們也不會修改這些包的代碼,可是每當咱們修改了業務代碼以後,這些包也會被從新打包。極大的浪費了時間,這時咱們就須要使用這個工具預先把靜態資源提早打包,之後修改源文件再打包時就不會打包這些靜態資源文件了。ios
咱們以 vue-cli 生成的項目爲例:git
## 全局安裝 vue-cli 腳手架 和 webpack cnpm install -g vue-cli webpack-dev-server ## 初始化項目 winpty vue.cmd init webpack vue-permission-manage cd vue-permission-manage ## 安裝基礎配置包 cnpm install ## 安裝依賴模塊(靜態資源) cnpm install vuex axios element-ui echarts -S
安裝完成後的目錄結構 (此處已經隱藏 node_modules 文件夾):
github
咱們編輯 main.js,引入咱們所安裝的靜態資源,結果爲:web
import 'babel-polyfill'; // The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue'; import App from './App'; import router from './router'; import store from './store/store.js'; import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; import '@/assets/css/normalize.css'; import '@/assets/css/common.scss'; import httpRequest from '@/assets/js/service/http.js'; import '@/assets/js/service/mock.js'; Vue.config.productionTip = false; Vue.use(ElementUI); Vue.prototype.$http = httpRequest; /* eslint-disable no-new */ new Vue({ el: '#app', router, store, components: { App }, template: '<App/>' });
回到命令窗口,執行打包命令:vue-router
## 編譯打包 npm run build
截圖中能夠看見 Time:65164ms,打包花費了65秒,vue 全家桶以及剛纔引入的各類包和源代碼所有被打包了。(打包時間也跟電腦配置有關,你們的都不同,可能個人筆記本比較low因此有點慢吧,影響不大,往下走)
咱們才引入了5-6個包而已,就已經花費了65秒,若是之後還要加上各類包及靜態資源,打包時間確定會更久。
這就是咱們爲何要引入 DllPlugin 的緣由!
咱們知道,咱們剛纔所引入的 vue 或者 axios 之類的,咱們只是使用它們,並不會改變它們的源碼,它們自己也不會運行,那麼咱們就能夠把這些模塊拆分出來提早打包。
那麼如何提早打包它們呢? 咱們在根目錄的 build 文件夾下建立一個 webpack 配置文件(webpack.dll.conf.js),既然這個文件是 webpack 配置文件,那麼它的格式確定也和 webpack 的其餘配置文件同樣:
var path = require('path'); var webpack = require('webpack'); /* 將特定的類庫提早打包而後引入,不但可以極大減小打包時間, 也實現了將公共代碼抽離成單獨文件的優化方案,能夠很大程度的減少打包以後的文件體積。 */ module.exports = { // 你想要提早打包的類庫的數組。注意 vue 要寫成別名 entry: { // 若是這些類庫有版本更新了(通常不多更新),就須要從新執行 npm run dll 打包類庫,再執行 npm run build 打包項目上線 // 這裏用 vendor 做爲 key 值表示後文用到的 [name] ,後續生成的打包文件就爲 vendor-manifest.json vendor.dll.js vendor: ['vue/dist/vue.esm.js', 'vuex', 'axios', 'vue-router', 'element-ui', 'echarts'] }, output: { path: path.join(__dirname, '../static/js'), // 打包後文件輸出的位置,放到項目根目錄的 static/js 下 filename: '[name].dll.js', // 打包後的文件名 vendor.dll.js library: '[name]_library' // vendor.dll.js 中暴露出的全局變量名,主要是給 DllPlugin 中的 name 使用。 // 因此這裏須要和 webpack.DllPlugin 中的 name: '[name]_library', 保持一致。 }, plugins: [ new webpack.DllPlugin({ // manifest.json 生成的文件夾及名字,這裏路徑寫成 .. 表明上一級目錄,也就是讓它生成在了根目錄下 path: path.join(__dirname, '../[name]-manifest.json'), // 和 output.library 保持一致便可 name: '[name]_library', // manifest 文件中請求的上下文,默認爲本文件的上下文 context: __dirname }), // 壓縮打包的文件,使用 UglifyJsPlugin 插件壓縮代碼 new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }) ] };
重點:這裏引入的 Dllplugin 插件,該插件將生成一個 manifest.json 文件,該文件供 webpack.dll.conf.js 中加入的 DllReferencePlugin 使用,使咱們所編寫的源文件能正確地訪問到咱們所須要的靜態資源(運行時依賴包)。相關字段的解釋已經在代碼註釋中寫明。
編寫該 webpack 配置以後,咱們就能夠預打包資源文件了。
## 以指定的 webpack 配置文件執行打包 webpack --config build/webpack.dll.conf.js
emmm。。。感受這命令有點難記哎,那咱們就將它加入 package.json 裏吧
"scripts": { "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", "lint": "eslint --ext .js,.vue src test/unit", "dll": "webpack --config build/webpack.dll.conf.js", "build": "node build/build.js" },
預打包資源文件:
npm run dll
能夠看到 dll 相關的資源文件已經打包成功,此時的目錄結構:
可見咱們的目錄結構中 static 下生成了 js 子目錄,打包好的 dll 文件(js/vendor.dll.js)就放在該目錄下,除此以外根目錄中還生成了 vendor-manifest.json。
如今咱們已經再也不須要將那些靜態資源包跟源文件一塊兒打包了,可是這也須要在源文件的 webpack.base.conf.js 中配置 DllReferencePlugin 使用 vendor-manifest.json 來引用這個 dll。
這一步咱們只須要改寫 vue-cli 爲咱們生成好的 build/webpack.base.conf.js
便可:
該文件主要是添加了 plugins 配置:
plugins: [ new webpack.DllReferencePlugin({ context: __dirname, // 與 Dllplugin 裏的 context 所指向的上下文保持一致,這裏都是指向了當前文件的 build 目錄 manifest: require('../vendor-manifest.json') // 引入 Dllplugin 所生成的的 manifest }) ],
到這裏配置完這個就。。哦還沒完別急,咱們須要手動在根目錄的 index.html 裏引入生成的 dll 庫
<body> <div id="app"></div> <!-- built files will be auto injected --> <script src="./static/js/vendor.dll.js"></script> <!--引入 vendor.dll.js --> </body>
好的,激動人心的時刻終於來了!!!咱們如今只須要 npm run build
看時間Time:20746ms!!!,比起以前的65秒咱們縮短到了20秒左右!時間就是$$,時間就是生命啊!!
日後若是咱們只是改動了業務代碼,就不須要從新打包那些個各類龐大的類庫了。不過還要注意一點,若是相關類庫版本更新了,再次執行 npm install 的時候類庫源碼有更新,此時就須要從新執行一下 npm run dll 再執行 npm run build。爲此,咱們在 package.json 再加一個命令 dll_build:
"scripts": { "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", "lint": "eslint --ext .js,.vue src test/unit", "dll": "webpack --config build/webpack.dll.conf.js", "build": "node build/build.js", "dll_build": "npm run dll && npm run build" },
第一次打包時,或者類庫版本更新了,執行 npm run dll_build
就行了~
到這裏優化就結束啦,文章有不妥的地方歡迎指出留言哦,以爲不錯的話點個贊點個星吧 hhh,github 源碼地址在文章開頭哦~
參考資料:
webpack 中文文檔 | webpack 中文網
webpack進階——DllPlugin優化打包性能(基於vue-cli)