欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript惰性加載的優(yōu)化技巧詳解

 更新時(shí)間:2025年04月09日 11:05:08   作者:大澤九章  
這篇文章主要為大家詳細(xì)介紹了JavaScript在進(jìn)行惰性加載時(shí)的一些優(yōu)化技巧,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

這是之前的一位朋友的酒桌之談,他之前負(fù)責(zé)的一個(gè)電商項(xiàng)目,剛剛開(kāi)發(fā)萬(wàn),首頁(yè)加載時(shí)間特別長(zhǎng),體驗(yàn)很差,所以就開(kāi)始排查,發(fā)現(xiàn)是在首頁(yè)一次性加載所有js導(dǎo)致的問(wèn)題,這個(gè)問(wèn)題在自己學(xué)習(xí)的時(shí)候并不明顯,往往被大家稱為編程習(xí)慣,甚至有的公司大佬進(jìn)行項(xiàng)目框架層級(jí)的硬性規(guī)定或者封裝,可以起到很好的作用,但是今天還是拿出來(lái)和大家分享一下:

場(chǎng)景描述

網(wǎng)站在首頁(yè)一次性加載了所有模塊的JavaScript資源,包括:

  • 首屏輪播圖
  • 商品推薦列表
  • 用戶評(píng)論模塊
  • 頁(yè)腳幫助中心
  • 未可視區(qū)域的廣告和營(yíng)銷組件

示例代碼

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

問(wèn)題

1.首屏加載時(shí)間過(guò)長(zhǎng)

用戶需要等待所有JS下載并執(zhí)行完才能看到首屏內(nèi)容

Lighthouse評(píng)分中"First Contentful Paint"指標(biāo)很差

2.帶寬浪費(fèi)

加載了用戶可能永遠(yuǎn)不會(huì)看到的資源(如未滾動(dòng)的底部?jī)?nèi)容)

3.主線程阻塞

大量JS同步執(zhí)行導(dǎo)致主線程長(zhǎng)時(shí)間忙碌

用戶交互(如點(diǎn)擊搜索框)出現(xiàn)延遲

4.內(nèi)存占用過(guò)高

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

排查思路

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

1.初步性能評(píng)估

打開(kāi)Chrome DevTools (F12)

  • 切換到 Network 面板
  • 勾選 Disable cache (模擬首次訪問(wèn))
  • 選擇 Fast 3G 網(wǎng)絡(luò)限速(放大問(wèn)題)

錄制加載過(guò)程

  • 刷新頁(yè)面開(kāi)始錄制
  • 觀察所有資源的加載順序和時(shí)間線

2.網(wǎng)絡(luò)面板分析

JS加載問(wèn)題識(shí)別

按類型篩選 JS 資源

檢查:

  • 是否首屏不需要的JS過(guò)早加載
  • 是否有大體積JS阻塞渲染(紅色長(zhǎng)條)
  • JS文件是否并行加載

關(guān)鍵指標(biāo)查看

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

3.性能面板深度分析

Performance面板錄制

  • 點(diǎn)擊 Record 后刷新頁(yè)面
  • 停止后查看時(shí)間線

關(guān)鍵區(qū)域檢查

Main 線程活動(dòng):

  • 長(zhǎng)任務(wù)(超過(guò)50ms的黃色塊)
  • JS編譯與執(zhí)行(紫色部分)

Network 網(wǎng)絡(luò)請(qǐng)求:

JS加載與執(zhí)行的關(guān)聯(lián)關(guān)系

Timings 標(biāo)記:

FP/FCP/FMP/LCP等關(guān)鍵時(shí)間點(diǎn)

典型問(wèn)題模式識(shí)別

// 問(wèn)題特征示例時(shí)間線:
[JS下載1][JS執(zhí)行1][JS下載2][JS執(zhí)行2]...
// 優(yōu)化后應(yīng)有:
[首屏JS下載][首屏渲染][惰性加載其他資源]

4.內(nèi)存面板檢查

Memory面板快照

取 Heap snapshot 比較:

  • 頁(yè)面剛加載時(shí)
  • 滾動(dòng)到底部后

內(nèi)存問(wèn)題識(shí)別

  • 檢查是否過(guò)早初始化了不必要組件
  • 查看保留的DOM節(jié)點(diǎn)數(shù)量是否異常

5.Lighthouse自動(dòng)化審計(jì)

生成報(bào)告

  • 切換到 Lighthouse 面板
  • 勾選 Performance 選項(xiàng)
  • 點(diǎn)擊 Generate report

關(guān)鍵指標(biāo)關(guān)注

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

6.具體問(wèn)題定位步驟

確定關(guān)鍵渲染路徑

在 Performance 錄制中:

  • 找到 FCP (First Contentful Paint)
  • 分析之前的所有JS活動(dòng)

識(shí)別非必要JS

// 在Console執(zhí)行:
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
  }))

加載順序可視化

使用 Network 的時(shí)序圖:

  • 拖動(dòng)選擇首屏?xí)r間段(0-FCP)
  • 右鍵 → "Save as HAR with content"

嘗試解決

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

1. 動(dòng)態(tài)導(dǎo)入 (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 />}>
        {/* 當(dāng)元素進(jìn)入視口時(shí)加載 */}
        <LazyLoadComponent>
          <Reviews />
        </LazyLoadComponent>
        <LazyLoadComponent>
          <Ads />
        </LazyLoadComponent>
        <LazyLoadComponent>
          <HelpCenter />
        </LazyLoadComponent>
      </Suspense>
    </>
  );
}

2. Intersection Observer實(shí)現(xiàn)視口觸發(fā)

// 自定義懶加載組件
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實(shí)現(xiàn) -->
<div class="lazy-image" data-src="product.jpg"></div>

性能影響數(shù)據(jù)(模擬)

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

這些細(xì)節(jié)往往很小,但是很多,歡迎各位小伙伴一起討論。

到此這篇關(guān)于JavaScript惰性加載的優(yōu)化技巧詳解的文章就介紹到這了,更多相關(guān)JavaScript惰性加載優(yōu)化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論