页面白屏时间优化

分析页面白屏的原因和优化方案

问题

用户打开页面后,从屏幕空白到显示第一个画面的时间过长,如何分析原因并进行优化?

解答

白屏产生的过程

从输入 URL 到页面显示的完整流程:

  1. 浏览器查找缓存(浏览器缓存 → 系统缓存 → 路由器缓存)
  2. DNS 解析获取 IP 地址
  3. 建立 TCP 连接(三次握手)
  4. 发送 HTTP 请求
  5. 服务器处理请求并返回响应
  6. 浏览器接收 HTML 并开始解析
  7. 构建 DOM 树和 CSSOM 树
  8. 生成渲染树并绘制页面

浏览器渲染机制

浏览器下载 HTML 后,首先解析头部代码进行样式表下载,然后构建 DOM 树。当 DOM 树构建完成后,立即开始构造 CSSOM 树。理想情况下两棵树并行构建,完成后生成渲染树并绘制。

需要注意的阻塞情况:

  • 内联 JS 代码会阻塞 DOM 树的构建
  • CSS 文件未下载完成时,会阻塞 JS 的执行
  • JS 执行被阻塞时,HTML 解析也会暂停

优化方案

DNS 解析优化

  • 启用 DNS 缓存
  • 使用 DNS 预解析:<link rel="dns-prefetch" href="//example.com">
  • 选择稳定可靠的 DNS 服务器

服务端优化

  • 使用 Redis 缓存
  • 数据库查询优化
  • 启用 Gzip 压缩
  • 优化服务器响应时间

资源加载优化

  • 精简 HTML 代码和结构
  • 优化 CSS 文件,移除无用样式
  • 将关键 CSS 内联到 HTML 中
  • JS 代码放在 </body> 前,避免使用内联 JS
  • 延迟加载首屏外的图片

图片懒加载实现

// 获取屏幕可视区域高度
const viewHeight = document.documentElement.clientHeight;

// 判断元素是否在可视区域
function isInViewport(element) {
  const offsetTop = element.offsetTop;
  return offsetTop < viewHeight;
}

// 懒加载图片
function lazyLoad() {
  const images = document.querySelectorAll('img[data-src]');
  images.forEach(img => {
    if (isInViewport(img)) {
      img.src = img.dataset.src;
      img.removeAttribute('data-src');
    }
  });
}

关键点

  • JS 会阻塞 DOM 构建,CSS 会阻塞 JS 执行,需要合理安排资源加载顺序
  • 将关键 CSS 内联到 HTML 中可以加快首屏渲染
  • 优先加载首屏内容,延迟加载首屏外的图片和资源
  • DNS 解析和服务器响应时间是白屏时间的重要组成部分
  • 减少 HTML、CSS、JS 文件体积,启用压缩可以缩短下载时间