• 优化浏览器渲染


    优化浏览器渲染,要从关键渲染路径出发,基本上是优化HTML、CSS、JS的依赖关系。

    其中HTML构建的DOM消耗是必须的。

    1. 从阻塞渲染的CSS出发

    CSS默认是阻塞渲染的资源。

    根据浏览器渲染的过程可知,浏览器渲染的基础是DOM和CSSOM。在生成CSSOM之前,不会渲染任何内容。

    生成CSSOM的过程是先从服务器下载CSS文件(不管阻塞与否都要先下载),然后过滤出阻塞渲染的CSS文件生成CSSOM。

    为了缩短生成CSSOM的时间:

    1. 应该尽量精简CSS

    2. 利用媒体类型和媒体查询来解除对渲染的阻塞。

    示例:(都会下载,但是只有满足media条件,才用于CSSOM)

    // 只有当页面>=400px时才会阻塞渲染
    <link href="./1.css" rel="stylesheet" media="(min-400px)">

    2. 从阻塞渲染的内联脚本出发

    在关键渲染路径中,如果HTML解析器遇到script标签,会暂停构建DOM,将控制权转给JS引擎,

    等js执行完成,再从之间暂停的地方继续构建DOM。也就是说,js脚本会阻碍DOM构建,延缓首次渲染。

    // 如果在js脚本执行过程中:
    --firefox浏览器会等js前的CSSOM构建完成再执行脚本;
    --webkit浏览器会暂停执行js脚本和DOM构建,直到完成CSSOM的下载和构建。

    js脚本执行使得DOM,CSSOM,JS之间出现了很多依赖关系,如等待CSSOM构建等。

    这会导致渲染出现延迟。

    解决方案:

    将脚本代码放到页面底部。

    这样还有一个好处,如果遇到处理DOM的情况,不会因为查询DOM失败而报错! 

    否则,要使用DOMContentLoad事件或者onload事件的回调函数来处理。

    3. 从阻塞渲染的JS文件下载出发 

    HTML解析器遇到外联script, 浏览器渲染暂停,先从磁盘/缓存/远程服务器获取获取脚本,下载时间大大阻塞了渲染。

    1. 将js文件放在不同的域名下

    该方法适用于图片,字体,样式,js等各种静态资源文件特别多的情况。

    因为同一域名下,TCP连接有限制,浏览器只能同时下载6~20个资源。

    如果来自不同的域名,就不会有这个限制。

    可以大大提升文件的下载速度。

    2. script添加async属性

    async属性只能用于外联脚本;内联脚本不能使用async属性。

    添加异步标识,会解除文件下载导致的渲染阻塞。

     <script src="../js/1.js" async></script>

    async属性的作用是: 使用另一个进程下载脚本,下载成功后立即执行。

    1. HTML解析器遇到async属性的script外联标签;
    2. 会继续HTML解析,同时并行下载js文件;
    3. 等js文件下载完成,暂停HTML解析,立即执行脚本;
    4. 脚本执行后,继续HTML解析。

    如果遇到多个含有async属性的script标签,执行顺序会按照下载完成的顺序。

    3. script标签添加defer属性

    defer属性只能用于外联script标签;内联脚本或者动态script标签无效。

    <script src="../js/1.js" defer></script>

    defer属性的作用:使用另一个进程下载文件,并且等DOM树构建完再执行脚本。

    1. HTML解析器遇到defer属性的script标签
    2. 继续解析HTML,同时并行下载js文件
    3. 解析HTML直到DOM构建完成
    4. 执行下载好的脚本文件

    执行脚本在DOMContentLoaded事件之前,DOM构建之后。

    如果遇到多个js文件同时具有defer属性,执行顺序按照页面上出现的顺序。

    async属性的优先级高于defer

    4. 脚本的动态加载

    动态生成script标签,插入页面,可以实现脚本的动态加载。

    ['a.js', 'b.js'].forEach(function(src) {
      var script = document.createElement('script');
      script.src = src;
      script.onload = function() {
        // 成功回调函数
      }
      script.onerror = function() {
        // 失败回调函数
      }
      document.head.appendChild(script);
    });

    动态加载的作用:使用另一个进程下载文件;默认执行顺序不确定,是下载完成的顺序。

    为了确定加载顺序,可以设置async属性为false。

    ['a.js', 'b.js'].forEach(function(src) {
      var script = document.createElement('script');
      script.src = src;
      script.async = false;
      document.head.appendChild(script);
    });

    这样可以保证执行顺序是数组中文件出现的顺序。

    但是后面如果还有脚本文件,会等数组中的文件全部执行完才会执行。

    4. 应用-js文件下载

    (为明显展示效果,Dev-tools设置了slow3G,且不使用css文件)

    当同步加载外部js文件时,会等js执行完再渲染;

      <head>
        <title>Critical Path: Measure Script</title>
        <meta name="viewport" content="width=device-width,initial-scale=1">
        <script src="./js/1.js"></script>
      </head>
      <body>
        <p>Hello <span>web performance</span> students!</p>
        <div><img width="100" height="100" src="./2.jpg"></div>
      </body>

    当使用async和defer属性时, 会先渲染已有DOM,再渲染图片和js修改的DOM;

  • 相关阅读:
    Access restriction on class due to restriction on required library rt.jar?
    Why “no projects found to import”?
    MySQL
    您对无法重新创建的表进行了更改或者启用了“阻止保存要求重新创建表的更改”选项
    INTJINTJ——内向+直觉+思维+判
    豆瓣网案例分析报告
    如何使用Git
    如何在不到六个月的时间内成为一个开发者
    关于网站编程Alex
    string
  • 原文地址:https://www.cnblogs.com/lyraLee/p/11875595.html
Copyright © 2020-2023  润新知