Skip to content

懒加载

本文档描述了对网站图片懒加载功能的全面优化,解决了"页面滑动快时,有些图片还没加载出来,会造成图片白一下"的问题。

📋 问题分析

原有的 HTML 原生懒加载 (loading="lazy") 虽然现代且高效,但存在以下问题:

  1. 触发阈值受限:原生懒加载的触发距离通常较小(几百像素),无法满足快速滑动时的加载需求
  2. 缺少占位机制:图片加载前没有尺寸占位,容易造成 layout shift
  3. 加载状态不明确:用户无法感知图片正在加载

🎯 优化目标

  1. 提前加载:扩大加载阈值,让图片在进入视口前就开始加载
  2. 占位防抖:为图片设置固定尺寸或比例占位,避免页面跳动
  3. 渐进加载:提供平滑的加载状态过渡
  4. 智能优化:根据设备类型和网络状况调整加载策略

🔧 实施方案

1. HTML 模板优化 (render-image.html)

改动内容:

  • 为所有图片添加 widthheight 属性
  • 使用 aspect-ratio CSS 属性确保占位效果
  • 保留原生 loading="lazy" 作为基础懒加载

关键改进:

<!-- 有尺寸信息的图片 -->
<img
  src="{{ $image.RelPermalink }}"
  width="{{ $image.Width }}"
  height="{{ $image.Height }}"
  style="aspect-ratio: {{ $image.Width }}/{{ $image.Height }}; max-width: 100%; height: auto;"
  loading="lazy"
  decoding="async">

<!-- SVG 图片 -->
<img
  src="{{ $image.RelPermalink }}"
  style="max-width: 100%; height: auto;"
  loading="lazy"
  decoding="async">

2. 增强懒加载脚本 (enhanced-lazy-loading.js)

核心功能:

2.1 可配置的预加载距离

const CONFIG = {
  rootMargin: '1200px 0px',    // 桌面端提前 1200px 加载
  rootMargin: '800px 0px',     // 移动端提前 800px 加载
  threshold: 0.01,
  eagerLoadCount: 3            // 首屏图片数量
};

2.2 智能首屏处理

  • 自动识别首屏图片,设置为 loading="eager"
  • 预加载关键图片(hero、featured 图片)

2.3 网络状况自适应

// 根据网络连接质量调整加载策略
if (connection.effectiveType === '2g') {
  CONFIG.rootMargin = '400px 0px';  // 慢速网络减少预加载
} else if (connection.effectiveType === '4g') {
  CONFIG.rootMargin = '1500px 0px'; // 快速网络增加预加载
}

2.4 页面可见性优化

  • 当页面从后台切换到前台时,立即加载视口内图片
  • 防止用户切换标签页导致的加载延迟

3. 样式优化 (enhanced-lazy-loading.scss)

关键样式:

3.1 图片占位效果

img[data-width][data-height] {
  aspect-ratio: attr(data-width) / attr(data-height);
  background-color: #f8f9fa;
  background-image: /* 纹理占位图案 */;
  transition: opacity 0.3s ease, filter 0.3s ease;
}

3.2 加载状态动画

.lazy-loading {
  opacity: 0.7;
  filter: blur(2px);
  animation: loading-pulse 1.5s ease-in-out infinite;
}

.lazy-loaded {
  opacity: 1;
  filter: none;
  transition: opacity 0.5s ease, filter 0.5s ease;
}

3.3 响应式优化

@media (max-width: 768px) {
  .lazy-loading {
    filter: blur(1px);  // 移动端减少模糊效果
  }
}

4. 与 BiggerPicture 集成

集成要点:

  • 监听 lazyImageLoaded 事件,为新加载的图片重新绑定点击事件
  • 确保懒加载图片加载完成后能正常在 lightbox 中显示
  • 维护图片的错误处理机制

📈 预期效果

性能提升

  1. 减少"白屏"现象:通过提前加载,快速滑动时图片能及时显示
  2. 消除布局跳动:图片占位确保页面布局稳定
  3. 平滑加载体验:渐进式加载状态提供视觉反馈

用户体验改善

  1. 滑动流畅性:图片提前加载,滑动时即时显示
  2. 视觉反馈:加载动画让用户了解图片正在加载
  3. 网络适配:根据网络状况智能调整加载策略

技术优势

  1. 向后兼容:保留原生懒加载作为基础,增强功能为补充
  2. 渐进增强:不支持 IntersectionObserver 时自动降级
  3. 性能可控:可根据实际情况调整配置参数

🎛️ 配置选项

enhanced-lazy-loading.js 中可以调整以下参数:

const CONFIG = {
  rootMargin: '1200px 0px',      // 预加载距离
  threshold: 0.01,               // 触发阈值
  eagerLoadCount: 3,             // 首屏图片数量
  enableProgressiveLoading: true  // 是否启用渐进加载
};

📱 移动端优化

  1. 减少预加载距离:移动端使用 800px 而非 1200px
  2. 优化动画效果:减少模糊程度避免性能问题
  3. 触摸体验:确保加载状态不影响触摸交互

🔍 监控与调试

脚本提供了详细的调试信息:

  • 图片加载状态日志
  • 预加载策略执行情况
  • 网络状况检测结果
  • 首屏图片识别结果

🚀 部署说明

  1. 文件更新
  2. layouts/_default/_markup/render-image.html - HTML 模板
  3. assets/js/enhanced-lazy-loading.js - 增强懒加载脚本
  4. assets/scss/enhanced-lazy-loading.scss - 样式文件
  5. layouts/partials/js-bundle.html - JavaScript 集成
  6. assets/scss/style.scss - 样式集成

  7. 构建要求

  8. Hugo 版本支持 aspect-ratio CSS 特性
  9. 现代浏览器支持 IntersectionObserver API

  10. 测试建议

  11. 在不同网络条件下测试加载效果
  12. 验证快速滑动时图片显示情况
  13. 检查移动端性能表现

📊 监测指标

建议监测以下指标来评估优化效果:

  • 图片加载完成率
  • 页面滑动流畅性
  • 用户停留时间
  • 图片查看率(BiggerPicture 打开次数)

通过这些优化,网站的图片加载体验将得到显著提升,特别是在快速滑动浏览时的表现。