javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > JavaScript惰性加载优化

JavaScript惰性加载的优化技巧详解

作者:大泽九章

这篇文章主要为大家详细介绍了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)

录制加载过程

2.网络面板分析

JS加载问题识别

按类型筛选 JS 资源

检查:

关键指标查看

- Waterfall流中查找:
  * 蓝色竖线(DOMContentLoaded)
  * 红色竖线(Load)
- 关注:
  * 首屏渲染完成时间
  * 主线程被JS执行阻塞的时间段

3.性能面板深度分析

Performance面板录制

关键区域检查

Main 线程活动:

Network 网络请求:

JS加载与执行的关联关系

Timings 标记:

FP/FCP/FMP/LCP等关键时间点

典型问题模式识别

// 问题特征示例时间线:
[JS下载1][JS执行1][JS下载2][JS执行2]...
// 优化后应有:
[首屏JS下载][首屏渲染][惰性加载其他资源]

4.内存面板检查

Memory面板快照

取 Heap snapshot 比较:

内存问题识别

5.Lighthouse自动化审计

生成报告

关键指标关注

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

6.具体问题定位步骤

确定关键渲染路径

在 Performance 录制中:

识别非必要JS

// 在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
  }))

加载顺序可视化

使用 Network 的时序图:

尝试解决

懒加载最直接的理解可以是按序加载,并不是一个很完整的操作,而是很多的细节拼凑或者是自己平常注意一种习惯吧。下面列出我自己习惯性的思路:

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

这些细节往往很小,但是很多,欢迎各位小伙伴一起讨论。

到此这篇关于JavaScript惰性加载的优化技巧详解的文章就介绍到这了,更多相关JavaScript惰性加载优化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文