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 這三個組件。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM