webpack性能優化(1):分隔/分包/非同步載入+組件與路由懶載入

来源:https://www.cnblogs.com/zhoulujun/archive/2023/03/18/17231355.html
-Advertisement-
Play Games

定義 如果希望動態給某個類添加一些屬性或者方法,但是你又不希望這個類派生的對象受到影響,那麼裝飾器模式就可以給你帶來這樣的體驗。 它的定義就是在不改變原對象的基礎上,通過對其進行包裝拓展,使得原有對象可以動態具有更多功能,從而滿足用戶的更複雜需求。 舉個例子,一部手機,你可以買各種花里胡哨的手機殼等 ...


webpack ensure相信大家都聽過。有人稱它為非同步載入,也有人說做代碼切割,那這個家伙到底是用來幹嘛的?其實說白了,它就是把js模塊給獨立導出一個.js文件的,然後使用這個模塊的時候,webpack會構造script dom元素,由瀏覽器發起非同步請求這個js文件。

這樣解決整個項目打包成同一個非常大js、css,首屏載入慢。其實和我們載入百度統計代碼類似, 把一些js模塊給獨立出一個個js文件,然後需要用到的時候,在創建一個script對象,加入到document.head對象中即可,瀏覽器會自動幫我們發起請求,去請求這個js文件,在寫個回調,去定義得到這個js文件後,需要做什麼業務邏輯操作。

什麼是懶載入

懶載入也叫延遲載入,即在需要的時候進行載入,隨用隨載。

當頁面中一個文件過大並且還不一定用到的時候,我們希望在使用到的時才開始載入,這就是按需載入。要實現按需載入,我們一般想到的方法:動態創建script標簽,並將src屬性指向對應的文件路徑

為什麼需要懶載入

在單頁應用中,如果沒有應用懶載入,運用webpack打包後的文件將會異常的大,造成進入首頁時,需要載入的內容過多,延時過長,不利於用戶體驗,而運用懶載入則可以將頁面進行劃分,需要的時候載入頁面,可以有效的分擔首頁所承擔的載入壓力,減少首頁載入時間

實現過程中存在的問題:

  • 怎麼保證相同的文件只載入一次?

  • 怎麼判斷文件載入完成?

  • 文件載入完成後,怎麼通知所有引入文件的地方?

webpcak 的按需載入已經完美解決了上述問題,但如何與webpack配合實現組件懶載入?

如何與webpack配合實現組件懶載入

webpack chunk 流

webpack配置文件中的output路徑配置chunkFilename屬性

output: {
    path: resolve(__dirname, 'dist'),
    filename:  '[name].js?[chunkhash]',
    chunkFilename: '[name].js?[hash:5]',
    publicPath: '/assets/'
},

chunkFilename路徑將會作為組件懶載入的路徑

webpack支持的非同步載入方法

System.import(); 

已廢除,不推薦——webpack2官網上已經聲明將逐漸廢除

() => system.import(URL)

() => import(URL)

需要webpack > 2.4,v1不支持——webpack2官網推薦使,官方文檔webpack中使用import(), 屬於es7範疇,

require是由webpack社區提供方案,import為es官方提供;

如果遇到使用import 報錯,需要安裝babelrc, 需要配合babel的syntax-dynamic-import插件使用, 具體使用方法如下

npm install --save-dev babel-core babel-loader babel-plugin-syntax-dynamic-import babel-preset-es2015

webpack babel-loader 需要配置

use: [{
  loader: 'babel-loader',
  options: {
    presets: [['es2015', {modules: false}]],
    plugins: ['syntax-dynamic-import']
  }
}]

使用如下

//導入整個模塊
import('./component').then(Component => /* ... */); 
//使用await
async function determineDate() {
  const moment = await import('moment');
  return moment().format('LLLL');
}
determineDate().then(str => console.log(str));

vue-router配置路由:vue官方文檔:路由懶載入(使用import())

{
  path: '/',
  component: () => import('../pages/home.vue'),
  meta: {
    title: 'home'
  }}

 

require.ensure

require.ensure([…modules],()=>{}[,errorCallBack[,chunkName]]);

v1和v2均可使用

require.ensure([], function() {
    var module = require('../../jsLib/module');
    //do something
})

require方式可以將多個模塊js組合分割打包,

require下麵方法ensure第一個參數是依賴,如果不需要請寫[](空數組)

而import只能將每個模塊獨立打包成一個js文件;

也就是說,如果現在有三個導航A、B、C,你現在用require可以將A單獨分割出來做懶載入,進入a模塊只請求A,B和C你可以組合在一起進行分割,進入B和C將載入共同一個文件;

component: resolve => require(['../pages/home.vue'], resolve)

vue-router配置路由,使用webpack的require.ensure技術,也可以實現按需載入。

{
  // 進行路由配置,規定'/'引入到home組件
  path: '/',
  component: resolve => require(['../pages/home.vue'], resolve),
  meta: {
    title: 'home'
}}

這是非同步載入組件,當你訪問 / ,才會載入 home.vue。

對於vue的路由配置文件(routers.js)

  • 用import引入的話,當項目打包時路由里的所有component都會打包在一個js中,造成進入首頁時,需要載入的內容過多,時間相對比較長。

  • 當用require這種方式引入的時候,會將你的component分別打包成不同的js,載入的時候也是按需載入,只用訪問這個路由網址時才會載入這個js。

你可以打包的時候看看目錄結構就明白了。 

  • require: 運行時調用,理論上可以運用在代碼的任何地方,
    import:編譯時調用,必須放在文件開頭

router中實現懶載入

vue的單頁面(SPA)項目,必然涉及路由按需的問題

路由中配置非同步組件

export default new Router({
    routes: [
        {
            mode: 'history',
            path: '/my',
            name: 'my',
            component:  resolve =>require(['../page/my/my.vue'], resolve),//懶載入
        },
    ]
})

 

實例中配置非同步組件

components: {
  historyTab: resolve => {require(['../../component/historyTab/historyTab.vue'], resolve)},//懶載入
  //historyTab: () => import('../../component/historyTab/historyTab.vue')
},

 

全局註冊非同步組件

Vue.component('mideaHeader', () => {
    System.import('./component/header/header.vue')
})

 

關於webpack非同步載入的問題

  • 多次進出同一個非同步載入頁面是否會造成多次載入組件?在多個地方使用同一個非同步組件時是否造成多次載入組件?

    否,首次需要用到組件時瀏覽器會發送請求載入組件,載入完將會緩存起來,以供之後再次用到該組件時調用

  • 如果在兩個非同步載入的頁面中分別同步與非同步載入同一個組件時是否會造成資源重用?

    會, 將會造成資源重用, 根據打包後輸出的結果來看, a頁面中會嵌入historyTab組件的代碼, b頁面中的historyTab組件還是採用非同步載入的方式, 另外打包chunk;在協同開發的時候全部人都使用非同步載入組件

  • 非同步載入頁面中載嵌入非同步載入的組件時對頁面是否會有渲染延時影響?

    會, 非同步載入的組件將會比頁面中其他元素滯後出現, 頁面會有瞬間閃跳影響;因為在首次載入組件的時候會有載入時間, 出現頁面滯後, 所以需要合理的進行頁面結構設計, 避免首次出現跳閃現象;

 

只要文章:

VUE2組件懶載入淺析 https://www.cnblogs.com/zhanyishu/p/6587571.html

解析 Webpack中import、require、按需載入的執行過程 https://segmentfault.com/a/1190000013630936

揭秘webpack按需載入原理 https://zhuanlan.zhihu.com/p/159216534

vue項目實現按需載入的3種方式:vue非同步組件、es提案的import()、webpack的require.ensure() https://segmentfault.com/a/1190000011519350

https://webpack.js.org/guides/code-splitting/


轉載本站文章《webpack性能優化(1):分隔/分包/非同步載入+組件與路由懶載入》,
請註明出處:https://www.zhoulujun.cn/html/tools/Bundler/webpackTheory/8384.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 前面我們簡單的瞭解了 vue 初始化時的一些大概的流程,這裡我們詳細的瞭解下具體的內容; 內容 這一塊主要圍繞init.ts中的initEvents進行剖析,初始化生命周期之後緊接著。 initEvents initEvents的方法位於scr/core/instance/events.ts中 ...
  • 新項目用 umi4-max 搭建,部分功能想要使用其他項目的功能,不想重新開發,想到了使用 webpack5 的聯邦模塊,可以直接引用其他項目代碼來實現共用代碼。 理想很美好,現實很殘酷。直接按照 webpack5 聯邦模塊的使用方法,並不能成功,而官方文檔沒有明確說明如何使用。 webpack 聯 ...
  • 深層次響應式 reactive 和 ref 創建的對象都是深層次的,對象的根屬性和嵌套屬性都是響應式的。 深層次轉換是遞歸地轉為響應式,對象里的每個屬性訪問都將觸發代理的依賴追蹤,這種性能負擔通常這隻有在處理超大型數組或層級很深的對象時才比較明顯。例如,一次渲染需要訪問 100000+ 個屬性時,才 ...
  • 原型模式(Prototype Pattern):使用原型實例指定創建對象的種類,並通過拷貝這些原型創建新的對象。 在JavaScript中,所有的對象都有一個原型鏈。原型鏈是一種機制,它允許我們在對象上定義屬性和方法,並且可以從它的原型中繼承屬性和方法。當我們訪問一個對象的屬性或方法時,JavaSc ...
  • 所周知,審查元素(F12或者右鍵檢查)的情況下,大家都可以隨機更改一部分頁面的代碼,註入惡意JS等等,這種情況避免也不難,雖然還能看到一部分H5源碼,但是無法修改;所以我們可以通過一下三種方式解決問題: 1、屏蔽F12 審查元素; 2、屏蔽右鍵菜單來初步解決這些問題(也就是解決發現問題的人[偷笑]) ...
  • 本文實例講述了JS實現的獲取銀行卡號歸屬地及銀行卡類型操作以及Luhn校驗演算法校驗銀行卡號演算法。分享給大家供大家參考,具體如下: javascript代碼如下 /** * Luhn校驗演算法校驗銀行卡號;Luhm校驗規則:16位銀行卡號(19位通用):1、將未帶校驗位的 15(或18)位卡號從右依次編 ...
  • CSS概念 css的使用是讓網頁具有統一美觀的頁面,css層疊樣式表,簡稱樣式表,文件尾碼名.css css的規則由兩部分構成:選擇器以及一條或者多條聲明 選擇器:通常是需要改變的HTML元素 聲明:由一個屬性和一個值組成,每個屬性有一個值,屬性和值使用類似key:value的形式(如下方h1就是選 ...
  • 多個路由通過路由器進行管理。 前端路由的概念和原理 (編程中的)路由(router)就是一組key-value對應關係,分為:後端路由和前端路由 後端路由指的是:請求方式、請求地址和function處理函數之間的對應關係 在SPA程式中,所有組件的展示和切換都在這唯一的一個頁面內完成,此時,不同組件 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...