JavaScript惰性加載優化實例

這是之前的一位朋友的酒桌之談,他之前負責的一個電商項目,剛剛開發萬,首頁加載時間特別長,體驗很差,所以就開始排查,發現是在首頁一次性加載所有js導致的問題,這個問題在自己學習的時候并不明顯,往往被大家稱為編程習慣,甚至有的公司大佬進行項目框架層級的硬性規定或者封裝,可以起到很好的作用,但是今天還是拿出來和大家分享一下:

場景描述

網站在首頁一次性加載了所有模塊的JavaScript資源,包括:

  • 首屏輪播圖

  • 商品推薦列表

  • 用戶評論模塊

  • 頁腳幫助中心

  • 未可視區域的廣告和營銷組件

示例代碼

// 問題代碼示例 - 同步加載所有腳本
import Carousel from './components/Carousel'; ? ? ? // 首屏必要
import ProductList from './components/ProductList'; // 首屏必要 
import Reviews from './components/Reviews'; ? ? ? ? // 需要滾動到中部才顯示
import Ads from './components/Ads'; ? ? ? ? ? ? ? ?// 頁尾才顯示
import HelpCenter from './components/HelpCenter'; ?// 頁腳折疊區域
?
function HomePage() {return (<><Carousel /><ProductList /><Reviews /><Ads /><HelpCenter /></>);
}

問題

  1. 首屏加載時間過長

    • 用戶需要等待所有JS下載并執行完才能看到首屏內容

    • Lighthouse評分中"First Contentful Paint"指標很差

  2. 帶寬浪費

    • 加載了用戶可能永遠不會看到的資源(如未滾動的底部內容)

  3. 主線程阻塞

    • 大量JS同步執行導致主線程長時間忙碌

    • 用戶交互(如點擊搜索框)出現延遲

  4. 內存占用過高

    • 初始化了所有組件,包括那些不需要立即顯示的

排查思路

這個排查的思路很通用,大部份性能問題都可以從這里著手,如果是前端的新朋友,那么建議從開頭編寫完代碼之后,多依著下面的排查思路看看自己的代碼執行步驟,然后思考,會有意想不到的收獲。

一、初步性能評估

  1. 打開Chrome DevTools (F12)

    • 切換到 Network 面板

    • 勾選 Disable cache (模擬首次訪問)

    • 選擇 Fast 3G 網絡限速(放大問題)

  2. 錄制加載過程

    • 刷新頁面開始錄制

    • 觀察所有資源的加載順序和時間線

二、網絡面板分析

  1. JS加載問題識別

    • 按類型篩選 JS 資源

    • 檢查:

      • 是否首屏不需要的JS過早加載

      • 是否有大體積JS阻塞渲染(紅色長條)

      • JS文件是否并行加載

  2. 關鍵指標查看

    markdown

    復制

    - Waterfall流中查找:* 藍色豎線(DOMContentLoaded)* 紅色豎線(Load)
    - 關注:* 首屏渲染完成時間* 主線程被JS執行阻塞的時間段

三、性能面板深度分析

  1. Performance面板錄制

    • 點擊 Record 后刷新頁面

    • 停止后查看時間線

  2. 關鍵區域檢查

    • Main 線程活動:

      • 長任務(超過50ms的黃色塊)

      • JS編譯與執行(紫色部分)

    • Network 網絡請求:

      • JS加載與執行的關聯關系

    • Timings 標記:

      • FP/FCP/FMP/LCP等關鍵時間點

  3. 典型問題模式識別

    javascript

    復制

    // 問題特征示例時間線:
    [JS下載1][JS執行1][JS下載2][JS執行2]...
    // 優化后應有:
    [首屏JS下載][首屏渲染][惰性加載其他資源]

四、內存面板檢查

  1. Memory面板快照

    • Heap snapshot 比較:

      • 頁面剛加載時

      • 滾動到底部后

  2. 內存問題識別

    • 檢查是否過早初始化了不必要組件

    • 查看保留的DOM節點數量是否異常

五、Lighthouse自動化審計

  1. 生成報告

    • 切換到 Lighthouse 面板

    • 勾選 Performance 選項

    • 點擊 Generate report

  2. 關鍵指標關注

    markdown

    復制

    - Opportunities中的建議:* "Defer offscreen images"* "Reduce unused JavaScript"
    - Diagnostics中的:* "Avoid enormous network payloads"* "JavaScript execution time"

六、具體問題定位步驟

  1. 確定關鍵渲染路徑

    • Performance 錄制中:

      • 找到 FCP (First Contentful Paint)

      • 分析之前的所有JS活動

  2. 識別非必要JS

    javascript

    復制

    // 在Console執行:
    performance.getEntriesByType('resource').filter(r => r.initiatorType === 'script').sort((a,b) => a.startTime - b.startTime).map(r => ({name: r.name.split('/').pop(),start: r.startTime,duration: r.duration}))
  3. 加載順序可視化

    • 使用 Network 的時序圖:

      • 拖動選擇首屏時間段(0-FCP)

      • 右鍵 → "Save as HAR with content"

嘗試解決

懶加載最直接的理解可以是按序加載,并不是一個很完整的操作,而是很多的細節拼湊或者是自己平常注意一種習慣吧。下面列出我自己習慣性的思路:

1. 動態導入 (Dynamic Import)
import { lazy, Suspense } from 'react';
?
const Reviews = lazy(() => import('./components/Reviews'));
const Ads = lazy(() => import('./components/Ads'));
const HelpCenter = lazy(() => import('./components/HelpCenter'));
?
function HomePage() {return (<><Carousel /><ProductList /><Suspense fallback={<Spinner />}>{/* 當元素進入視口時加載 */}<LazyLoadComponent><Reviews /></LazyLoadComponent><LazyLoadComponent><Ads /></LazyLoadComponent><LazyLoadComponent><HelpCenter /></LazyLoadComponent></Suspense></>);
}
2. Intersection Observer實現視口觸發
// 自定義懶加載組件
const LazyLoadComponent = ({ children }) => {const ref = useRef();const [isVisible, setIsVisible] = useState(false);
?useEffect(() => {const observer = new IntersectionObserver(([entry]) => {if (entry.isIntersecting) {setIsVisible(true);observer.disconnect();}},{ threshold: 0.1 });observer.observe(ref.current);return () => observer.disconnect();}, []);
?return <div ref={ref}>{isVisible && children}</div>;
};

3. 圖片/iframe懶加載

<!-- 使用原生loading屬性 -->
<img src="product.jpg" loading="lazy" alt="Product">
?
<!-- 或使用Intersection Observer實現 -->
<div class="lazy-image" data-src="product.jpg"></div>

性能影響數據(模擬)

指標非惰性加載惰性加載優化后
首屏加載時間4.2s1.8s
總JS體積1.8MB650KB(首屏)
Lighthouse性能評分4882
首次輸入延遲(FID)320ms110ms

這些細節往往很小,但是很多,歡迎各位小伙伴一起討論。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/900611.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/900611.shtml
英文地址,請注明出處:http://en.pswp.cn/news/900611.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

蘋果內購支付 Java 接口

支付流程&#xff0c;APP支付成功后 前端調用后端接口&#xff0c;后端接口將前端支付成功后拿到的憑據傳給蘋果服務器檢查&#xff0c;如果接口返回成功了&#xff0c;就視為支付。 代碼&#xff0c;productId就是蘋果開發者后臺提前設置好的 產品id public CommonResult<S…

數據庫中的數組: MySQL與StarRocks的數組操作解析

在現代數據處理中, 數組 (Array) 作為一種高效存儲和操作結構化數據的方式, 被廣泛應用于日志分析, 用戶行為統計, 標簽系統等場景. 然而, 不同數據庫對數組的支持差異顯著. 本文將以MySQL和StarRocks為例, 深入解析它們的數組操作能力, 并對比其適用場景. 文章目錄 一 為什么需…

LeetCode零錢兌換(動態規劃)

題目描述 給你一個整數數組 coins &#xff0c;表示不同面額的硬幣&#xff1b;以及一個整數 amount &#xff0c;表示總金額。 計算并返回可以湊成總金額所需的 最少的硬幣個數 。如果沒有任何一種硬幣組合能組成總金額&#xff0c;返回 -1 。 你可以認為每種硬幣的數量是無…

/sys/fs/cgroup/memory/memory.stat 關鍵指標說明

目錄 1. **total_rss**2. **total_inactive_file**3. **total_active_file**4. **shmem**5. **其他相關指標**總結 以下是/sys/fs/cgroup/memory/memory.stat文件中一些關鍵指標的詳細介紹&#xff0c;特別是與PostgreSQL相關的指標&#xff1a; 1. total_rss 定義&#xff1…

C++第14屆藍橋杯b組學習筆記

1. 日期統計 小藍現在有一個長度為 100100 的數組&#xff0c;數組中的每個元素的值都在 00 到 99 的范圍之內。數組中的元素從左至右如下所示&#xff1a; 5 6 8 6 9 1 6 1 2 4 9 1 9 8 2 3 6 4 7 7 5 9 5 0 3 8 7 5 8 1 5 8 6 1 8 3 0 3 7 9 2 7 0 5 8 8 5 7 0 9 9 1 9 4 4…

[Effective C++]條款28:避免返回handles指向對象內部成分

. 在C中&#xff0c;返回指向對象內部成分的引用&#xff08;handles&#xff09;可能會導致封裝性降低和對象空懸問題。為了避免這些問題&#xff0c;可以通過返回const引用來限制對內部數據的修改&#xff0c;從而確保只讀訪問 1、返回內部引用對象 下面代碼中getData函數返…

PyTorch 學習筆記

環境&#xff1a;python3.8 PyTorch2.4.1cpu PyCharm 參考鏈接&#xff1a; 快速入門 — PyTorch 教程 2.6.0cu124 文檔 PyTorch 文檔 — PyTorch 2.4 文檔 快速入門 導入庫 import torch from torch import nn from torch.utils.data import DataLoader from torchvision …

windows開啟wsl與輕量級虛擬機管理

基于win 10 打造K8S應用開發環境&#xff08;wsl & kind&#xff09; 一、wsl子系統安裝 1.1 確認windows系統版本 cmd/powershell 或者win r 運行winver 操作系統要> 19044 1.2 開啟wsl功能 控制面板 -> 程序 -> 啟用或關閉Windows功能 開啟適用于Linux的…

C++ -異常之除以 0 問題(整數除以 0 編譯時檢測、整數除以 0 運行時檢測、浮點數除以 0 編譯時檢測、浮點數除以 0 運行時檢測)

一、整數除以 0&#xff08;編譯時檢測&#xff09; 1、演示 #include <iostream>using namespace std;int main() {int result 10 / 0;cout << result << endl;return 0; }程序無法運行&#xff0c;輸出結果 error C2124: 被零除或對零求模2、演示解讀 …

【藍橋杯】搜索算法:剪枝技巧+記憶化搜索

1. 可行性剪枝應用 1.1. 題目 題目描述: 給定一個正整數n和一個正整數目標值target,以及一個由不同正整數組成的數組nums。要求從nums中選出若干個數,每個數可以被選多次,使得這些數的和恰好等于target。問有多少種不同的組合方式? 輸入: 第一行:n和target,表示數組…

Uniapp 集成極光推送(JPush)完整指南

文章目錄 前言一、準備工作1. 注冊極光開發者賬號2. 創建應用3. Uniapp項目準備 二、集成極光推送插件方法一&#xff1a;使用UniPush&#xff08;推薦&#xff09;方法二&#xff1a;手動集成極光推送SDK 三、配置原生平臺參數四、核心功能實現1. 獲取RegistrationID2. 設置別…

Linux中進程

一、認識進程 進程(PCB)內核數據結構(task_struct)程序的代碼和數據 每一個進程都有其獨立的task_struct,OS對眾多的task_struct進行管理&#xff0c;如何管理&#xff1f;先描述再組織&#xff0c;所有運?在系統?的進程都以task_struct鏈表的形式存在內核?&#xff0c;而…

國外的AI工具

一 OpenAI &#xff1a; &#x1f4a1; 總覽&#xff1a; 名稱全稱/代號簡介GPT-4o“o” omniOpenAI 最新的旗艦多模態模型&#xff08;文字、圖像、音頻三模態&#xff09;&#xff0c;比 GPT-4 更強、更快、更便宜。GPT-4o-mini精簡版 GPT-4o輕量級版本&#xff0c;推測為性…

企業級Java開發工具MyEclipse v2025.1——支持AI編碼輔助

MyEclipse一次性提供了巨量的Eclipse插件庫&#xff0c;無需學習任何新的開發語言和工具&#xff0c;便可在一體化的IDE下進行Java EE、Web和PhoneGap移動應用的開發&#xff1b;強大的智能代碼補齊功能&#xff0c;讓企業開發化繁為簡。 立即獲取MyEclipse v2025.1正式版 具…

按鍵長按代碼

這些代碼都存放在定時器中斷中。中斷為100ms中斷一次。 數據判斷&#xff0c;看的懂就看吧

在 macOS 上連接 PostgreSQL 數據庫(pgAdmin、DBeaver)

在 macOS 上連接 PostgreSQL 數據庫 pgAdmin 官方提供的圖形化管理工具&#xff0c;支持 macOS。 下載地址&#xff1a;https://www.pgadmin.org/ pgAdmin 4 是對 pgAdmin 的完全重寫&#xff0c;使用 Python、ReactJs 和 Javascript 構建。一個用 Electron 編寫的桌面運行時…

FTP協議和win server2022安裝ftp

FTP協議簡介 FTP&#xff08;File Transfer Protocol&#xff0c;文件傳輸協議&#xff09;是一種用于在網絡上的計算機之間傳輸文件的標準網絡協議。它被廣泛應用于服務器與客戶端之間的文件上傳、下載以及管理操作。FTP支持多種文件類型和結構&#xff0c;并提供了相對簡單的…

人工智能——AdaBoost算法

目錄 摘要 13 AdaBoost算法 13.1 本章工作任務 13.2 本章技能目標 13.3 本章簡介 13.4 編程實戰 13.5 本章總結 13.6 本章作業 本章已完結! 摘要 本章實現的工作是:首先采用Python語言讀取數據并構造訓練集和測試集。然后建立AdaBoost模型,利用訓練集訓練該模型,…

DFS 藍橋杯

最大數字 問題描述 給定一個正整數 NN 。你可以對 NN 的任意一位數字執行任意次以下 2 種操 作&#xff1a; 將該位數字加 1 。如果該位數字已經是 9 , 加 1 之后變成 0 。 將該位數字減 1 。如果該位數字已經是 0 , 減 1 之后變成 9 。 你現在總共可以執行 1 號操作不超過 A…

【開發經驗】調試OpenBMC Redfish EventService功能

EventService功能是Redfish規范中定義的一種事件日志的發送方式。用戶可以設置訂閱者信息(通常是一個web服務器)&#xff0c;當產生事件日志時&#xff0c;OpenBMC可以根據用戶設置的訂閱者信息與對日志的篩選設置&#xff0c;將事件日志發送到訂閱者。 相比于傳統的SNMPTrap日…