1. 程式人生 > >Vue.js中用webpack合併打包多個元件並實現按需載入

Vue.js中用webpack合併打包多個元件並實現按需載入

對於現在前端外掛的頻繁更新,所以多多少少要對元件化有點了解,下面這篇文章主要給大家介紹了在Vue.js中用webpack合併打包多個元件並實現按需載入的相關資料,需要的朋友可以參考下。  

前言

隨著移動裝置的升級、網路速度的提高,使用者對於web應用的要求越來越高,web應用要提供的功能越來越。功能的增加導致的最直觀的後果就是資原始檔越來越大。為了維護越來越龐大的客戶端程式碼,提出了模組化的概念來組織程式碼。webpack作為一種模組化打包工具,隨著react的流行也越來越流行。

使用 Vue 開發專案時,如果要使用其單檔案元件特性,必然要使用 webpack 或者 browserify 進行打包,對於大型應用,為了提升載入速度,可以使用 webpack 的 code split 功能進行分割打包,生成較小的模組並按需載入,這在 Vue 文件及 vue-router 文件中均有介紹:

Async ComponentsLazy Loading

webpack 的 code split 可以使用 webpack 的 require.ensure 特殊語法或者使用 AMD 風格的 callback-require 語法,以 AMD 風格的 callback-require 語法為例——

全域性註冊 Async Component:

 
1 2 3 4 let myAsyncComponent = resolve => {   require([ './my-async-component' ], resolve) } Vue.component( 'async-webpack-example' , myAsyncComponent)

區域性註冊 Async Component,單檔案元件中 script 塊內容:

 
1 2 3 4 5 6 7 8 9 10 let myAsyncComponent = resolve => {   require([ './my-async-component' ], resolve) }   // Vue 擴充套件例項選項,其他選項略 export default {   components: {   'async-webpack-example' : myAsyncComponent   } }

在使用 vue-router 時,為實現不同路由下的元件非同步載入,在路由對映中可以使用同樣的方式來設定路由項的 component 屬性。

這裡的 myAsyncComponent 被定義為一個工廠函式,在需要時才會以 Vue 或者 vue-router 定義的用於解析元件選項的 resolve 回撥函式(是的,在 Vue 和 vue-router 中有兩個不同的解析元件選項的函式)為引數執行 callback-require 函式(resolve 回撥函式的引數是元件選項),這樣,在執行打包指令碼時,my-async-component.vue 檔案會被單獨打包成一個檔案,並且僅當該元件被使用時才會載入。

當要求非同步載入的元件較多時,將會生成更多的單個檔案,對於前端效能而言,雖然每個檔案更小了,但可能意味著更多的網路連線建立和關閉的開銷,因此在前端優化的實踐中,通常需要在檔案數量和單個檔案大小之間取得平衡。

本文介紹如何將多個元件合併打包成一個單獨的檔案,一方面可以減少程式碼塊的數量,另一方面,如果合併打包的這些元件在不同地方多次重複使用,由於 Vue 的快取機制,可以加快後續元件的載入速度,並且如果這些通用元件長時間不會變化(如 UI 相關的元件),打包生成的檔案也長期不會變化,可以充分利用瀏覽器的快取功能,實現前端載入速度的優化。

先上效果圖,在使用 vue-router 的 SPA 應用中,將除根路由之外的路由項對應的 ComponentA、ComponentB、ComponentC 等三個元件合併打包成一個檔案。初次載入頁面時,從開發者工具的 Network 面板上可以看到,此時未載入包含 ComponentA、ComponentB、ComponentC 這三個元件的 0.a5a1bae6addad442ac82.js 檔案,當點選 Page A 連結時,載入了該檔案,然後再點選 Page B、Page C 連結時,沒有重新載入該檔案。

我們首先通過 vue-cli 命令列工具使用 webpack 專案模板建立一個包含 vue-router 的專案,在其 src/components 目錄下建立一個 CommonComponents 目錄,在該目錄中建立 ComponentA、ComponentB、ComponentC 這三個元件。

同時在 CommonComponents 目錄下建立 index.js,其內容如下:

 
1 2 3 exports.ComponentA = require( './ComponentA' ) exports.ComponentB = require( './ComponentB' ) exports.ComponentC = require( './ComponentC' )

這樣,我們只需要使用 webpack 的 require.ensure 特殊語法或者使用 AMD 風格的 callback-require 語法非同步載入 CommonComponents 目錄下的 index.js,在使用 webpack 進行打包時,就可以實現將 ComponentA、ComponentB、ComponentC 這三個元件合併打包。以 AMD 風格的 callback-require 語法為例示範如下,這裡的 callback 回撥函式的形式沒有任何特殊要求。

 
1 2 3 require([ 'component/CommonComponents' ], function (CommonComponents) {   // do whatever you want with CommonComponents })

component/CommonComponents 模組載入成功時,這裡的回撥函式中的 CommonComponents 引數將會是一個包含 ComponentA、ComponentB、ComponentC 這三個元件選項的物件。

在定義非同步解析元件時,我們使用的是一個工廠函式 resolve => {require(['./my-async-component'], resolve)},如果需要在路由配置檔案中新增 component 屬性為 ComponentA 元件的路由項,應該定義什麼樣的工廠函式呢?記住這裡的 resolve 是一個用於解析元件選項的回撥函式,其引數是所獲取的元件選項,而上一段程式碼中的 CommonComponents 恰好是包含若干個元件選項的物件,因此我們可以將 CommonComponents 的子屬性作為引數用於 resolve 呼叫,我們編寫一個函式 getCommonComponent,用於根據元件名稱返回獲取相應的元件選項的工廠函式。

 
1 let getCommonComponent = componentName => resolve => require([ 'components/CommonComponents' ], components => resolve(components[componentName]))

在元件模板或者路由對映等使用其中某一個元件的地方,可以使用類似於 getCommonComponent('ComponentA') 這樣的函式呼叫進行元件設定,在路由對映中的使用示例如下:

 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 routes: [   {   path: '/' ,   name: 'Hello' ,   component: Hello   },   {   path: '/a' ,   name: 'A' ,   component: getCommonComponent( 'ComponentA' )   },   {   path: '/b' ,   name: 'B' ,   component: getCommonComponent( 'ComponentB' )   },   {   path: '/c' ,   name: 'C' ,   component: getCommonComponent( 'ComponentC' )   } ]

最終打包生成的檔案列表如下圖所示,其中的 0.a5a1bae6addad442ac82.js 包含了 ComponentA、ComponentB、ComponentC 這三個元件。