白屏时间计算及优化策略

117 阅读2分钟

白屏时间如何界定

用户输入地址,到看到内容的这个时间内,页面存在的白屏时间。

浏览器做了以下操作:

  1. dns解析:将域名解析为ip地址;
  2. 建立tcp链接:三次握手;
  3. 发起http请求:浏览器向服务器发送请求;
  4. 服务器响应;
  5. 浏览器解析html生成dom树;
  6. 浏览器解析css生成cssom,并结合dom树生成布局树,从而实际进行渲染;
  7. 页面进行展示

根据操作可以归纳出以下的影响要素

  1. 网速、网络稳定性:网络延迟、带宽、dns解析时长等等。
  2. 服务器性能:提高服务器响应速度,这个是后端考虑的范畴了
  3. 前端页面结构:HTML文档的大小、复杂度、外部资源的加载顺序等都会影响白屏时间。如果HTML文档过大或包含大量外部资源,浏览器需要更长的时间来解析和渲染页面。
  4. 浏览器性能:浏览器的渲染引擎性能、缓存机制等也会影响白屏时间。不同浏览器的渲染性能存在差异,导致白屏时间不同。

对策

  1. 开启dns预解析(dns-prefetch),站点进行cdn部署

  2. 开启http缓存,结合构建工具合理配置分包策略,充分利用浏览器缓存

  3. 开启脚本的异步加载,async、defer方案。

    a. async标签的script,浏览器遇见会立即加载立即运行,会阻塞html解析,不保证执行顺序
    b. defer标签的script,浏览器立即立即加载但延迟运行,不会阻塞解析,保证执行顺序
    c. 指定rel="prefecth"的link,浏览器空闲时拉取并存入缓存,且不阻塞正常解析,,不保证资源之间的执行顺序。
    d. 指定rel="preload"的link,希望浏览器尽早的请求资源,且不阻塞正常的onload,不保证资源之间的执行顺序。
    preload必须设置as属性来声明资源的类型(font/image/style/script等),否则浏览器可能无法正确加载资源。对于字体文件或者可以加载的跨域资源需要加上crossorigin属性。

如何计算白屏时长

  1. 手动计算
<!DOCTYPE html>  
<html lang="en">  
<head>  
<meta charset="UTF-8">  
<meta name="viewport" content="width=device-width, initial-scale=1.0">  
<title>白屏时间计算</title>  
<script>  
    // 记录页面开始加载的时间  
    window.pageStartTimeDate.now();  
  </script>  
<link rel="stylesheet" href="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-assets/ionicons/2.0.1/css/ionicons.min.css~tplv-t2oaga2asx-image.image">  
<link rel="stylesheet" href="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-assets/asset/fw-icon/1.0.9/iconfont.css~tplv-t2oaga2asx-image.image">  
  
<script>  
    // head 解析完成后,记录时间  
    window.firstPaintDate.now();  
    console.log(`白屏时间:${firstPaint - pageStartTime}ms`);  
  </script>  
</head>  
<body>  
<div class="container"></div>  
</body>  
</html>
  1. Performance Api
// 性能 观察器   观察者模式  
    const observer = new PerformanceObserver((list) => {  
      // 获取所有的 性能 指标  
      const entries = list.getEntries();  
      for(const entry of entries) {  
        // body 里的第一个 标签的渲染  
        // 'first-paint' 表示页面首次开始绘制的时间点,也就是白屏结束的时间点  
        if(entry.name === 'first-paint') {  
          const whiteScreenTime = entry.startTime;  
          console.log(`白屏时间:${whiteScreenTime}ms`);  
        }  
      }  
    })  
    // 首次绘制  first-paint  
    // 首次内容绘制  first-contentful-paint 事件  
    // observe 监听性能指标  
    // buffered 属性设置为 true,表示包含性能时间线缓冲区中已经记录的相关事件  
    // 这样即使在创建 PerformanceObserver 之前事件已经发生,也能被捕获到  
    observer.observe({ type'paint'bufferedtrue });