懒加载 和 预加载

150 阅读3分钟

关键词:

- 懒加载
    - 原生标签 loading="lazy"
    - 手动实现 IntersectionObserver API
- 预加载
    - 原生link标签设置 rel="perload"

懒加载

  • 核心

    • 延迟加载非首屏或用户未触达区域等资源,减少初始请求数量,提升首屏速度
  • 图片

    • 原生(推荐)
      • 现代浏览器支持loading="lazy"属性,适用于<img><iframe>
      <img 
          src="placeholder.jpg" 
          data-src="real-image.jpg" 
          loading="lazy" 
          alt="Lazy-loaded Image"
      >
      
      • 特性
        • 浏览器自动处理,当图片进入视口时加载真实资源
        • 兼容性:Chrome 77+、Firefox 75+、Edge 79+,Safari 15.4+
      • 注意
        • 首屏关键图片避免使用,防止影响LCP(最大内容绘制)
    • 手动实现(兼容旧浏览器)
      • 使用Intersection ObserverAIP监听元素是否进入视口
      <img data-src="real-image.jpg" class="lazyload" alt="Lazy Image">
      <script>
          const observer = new IntersectionObserver((entries) => {
              entries.forEach(entry => {
              if (entry.isIntersecting) {
                  // 已经进入视口 后进行操作
                  const img = entry.target;
                  img.src = img.dataset.src;
                  observer.unobserve(img); // 加载后停止观察
              }
              });
          });
          document.querySelectorAll('.lazyload').forEach(img => observer.observe(img));
      </script>
      
      • 优化点
        • 添加占位图(低质量模糊图LQIP)避免布局偏移(CLS)
        • 结合srcset实现响应式图片懒加载
    • 第三方库
      • lozad.js
        • 轻量级懒加载库,支持图片,视频,背景图
      • yall.js
        • 兼容IE11懒加载方案
  • 视频

    • 视频体积更加,懒加载更关键
    <video 
        controls 
        preload="none" 
        poster="video-poster.jpg"
        data-src="video.mp4"
        class="lazyload-video"
        >
        <source data-src="video.webm" type="video/webm">
        </video>
    
        <script>
        document.querySelectorAll('.lazyload-video').forEach(video => {
            const observer = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                video.querySelectorAll('source').forEach(source => {
                    source.src = source.dataset.src;
                });
                video.load(); // 触发视频加载
                observer.unobserve(video);
                }
            });
            });
            observer.observe(video);
        });
        </script>
    
    • 优点
      • 使用preload="none"禁止自动预加载
      • 使用poster属性设置视频封面图,提升用户体验
  • 预加载

    • 核心
      • 提前加载后续可能需要点资源,减少等待延迟
    • 关键资源
      • 使用<link rel="perload">
      <!-- 预加载字体、CSSJS、图片 -->
      <link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
      <link rel="preload" href="critical.css" as="style">
      <link rel="preload" href="main.js" as="script">
      <link rel="preload" href="hero-image.jpg" as="image">
      
      • 特性
        • 浏览器优先级高,但需要确保资源确实会被使用
        • 支持类型:script / style / image / font / document 等
    • 非关键资源
      • 动态预加载(用户行为预测)
        • 根据用户行为(悬停,路由变化)触发预加载
        // 鼠标悬停时预加载图片
        document.querySelector('.gallery-link').addEventListener('mouseover', () => {
            const img = new Image();
            img.src = 'next-page-image.jpg';
        });
        
        // 路由跳转前预加载资源
        router.beforeEach((to, from, next) => {
            preloadResources(to.path); // 根据路由预加载 JS/CSS
            next();
        });
        
      • 视频预加载
        • 预加载元数据
          • 设置perload="metadata",仅加载视频时长和尺寸等基础信息
          <!-- preload 属性可选值:none、metadata、auto -->
          <video width="320" height="240" controls preload="metadata">
              <source src="https://example.com/video.mp4" type="video/mp4">
              您的浏览器不支持视频播放。
          </video>
          // none:不进行预加载。
          // metadata:只预加载视频的元数据(如时长、尺寸等)。
          // auto:浏览器自行决定是否预加载视频内容。
          

懒加载和预加载实际运用

  • 电商商品列表
    • 首屏优化
      • 使用loading="lazy"懒加载首屏外的商品图片
      • 预加载当前页面的关键CSS和字体
    • 用户行为预测
      • 当用户滚动到列表底部时,预加载下一页数据
      • 鼠标悬停在商品卡片时,预加载详情页的JS和图片
    • 视频优化
      • 懒加载商品介绍视频,仅加载用户点击播放时的资源

注意事项

  • 懒加载

    • 避免过度使用
      • 首屏关键资源禁止懒加载,否则影响LCP(最大内容绘制)
    • 兼容处理
      • 旧浏览器使用 Intersection Observer Polyfii
    • 骨架屏占位
      • 避免懒加载导致布局偏移(CLS)
  • 预加载

    • 优先级控制
      • 滥用预加载可能挤压带宽,反而降低性能
    • 缓存策略
      • 预加载资源应该设置合理缓存(如 Cache-Control)
  • SEO友好

    • 懒加载图片需提供原生src的替代方案(如<noscript>标签)
  • 检测工具

    • Lighthouse
      • 检测未正确懒加载的资源
    • Chrome DevTools Nework Panel
      • 模拟慢网络,观察资源加载顺序
    • Quicklink
      • Google的预加载库,基于视口和网络空闲时间预加载连接资源