• 浏览器渲染页面的探讨


    我们都知道,网页中引用的外部文件: JavaScritp、CSS 等常常会阻塞浏览器渲染页面,执行一大片js代码也会迟滞页面的渲染。假设在 <head> 中引用的某个 JavaScript 文件由于各种不给力需要2秒来加载;或者,我们在页面中插入某段执行起来很耗时的js代码,那么浏览器渲染页面的过程就会被阻塞,直到JS文件下载并执行完后才继续。由此可见,前端性能调优时必须排除任何潜在的渲染阻塞点,让浏览器在最短时间内渲染出整体页面。

    先来看看,为什么会发生渲染阻塞?

    例如:有如下的html文件

    <!doctype html>
    <html>
      <head>
        <script type="text/javascript" src="page.js"></script>
      </head>
      <body>
        <h1>Hello World</h1>
      </body>
    </html>

    上述代码中,当浏览器解析 script 标签时,由于浏览器并不知道 page.js 将会对页面做什么改变,所以浏览器需要停止渲染,下载并执行 page.js 后再继续渲染后面的内容。如果 page.js 的下载过程中出现任何延迟,也将影响整个页面的渲染。对此,我们可以有如下解决办法:

    1、如果页面的初始渲染的确依赖于page.js,我们可以考虑使用内联JavaScript(一般很少看到有项目这么做)。

     <!doctype html>
    <html>
      <head>
        <script type="text/javascript">
        /* page.js的内容 */
        </script>
      </head>
      <body>
        <h1>Hello World</h1>
      </body>
    </html>

    2、如果页面的初始渲染并不依赖于page.js,我们可以考虑推迟加载page.js,让其在页面初始内容渲染完成后再加载。

    <!doctype html>
    <html>
      <head>
      </head>
      <body>
        <h1>Hello World</h1>
        <script type="text/javascript" src="page.js"></script>
      </body>
    </html>

    3、HTML5这个前几年发布的新东东已经允许我们给 script 标签添加属性: "async" 来告诉浏览器不必停下来等待该脚本执行,什么时候下载完什么时候执行该脚本就可以了。这样的话浏览器会边下载page.js边渲染后面的内容。

    <!doctype html>
    <html>
      <head>
        <script type="text/javascript" src="page.js" async></script>
      </head>
      <body>
        <h1>Hello World</h1>
      </body>
    </html>

    然而如果某个JS被其他JS所依赖,那么就不能使用异步加载了。

    <!doctype html>
    <html>
      <head>
        <script type="text/javascript" src="jquery-1.11.3.min.js" async></script>
        <script type="text/javascript" src="jq-plugin.js" async></script>
      </head>
      <body>
        <h1>Hello World</h1>
      </body>
    </html>

    由于使用异步加载后,JS不再顺序执行。上例中 jq-plugin.js 依赖于jQuery,如果 jq-plugin.js 先下载完成,此时jQuery还没下载完,那么浏览器就会先执行 jq-plugin.js 导致出错。这里可以实行依赖加载,requireJs即提供了较好的解决办法,此处可以用requireJs依赖加载来避免,总之requireJs好处多多,这里暂时不予大篇幅讨论,请参见我的另一篇博文 requireJs实现前端框架。

    再来看为什么css文件加载也会导致阻塞呢?

    由于CSS决定了DOM元素的样式、布局,所以浏览器遇到CSS文件时会等待CSS文件加载并解析完后才继续渲染页面。也有一些对策来解决这个问题:

    1、我们可以将那些页面首屏渲染需要用到的CSS代码加入Inline CSS。

    <!doctype html>
    <html>
      <head>
        <style tpe="text/css">
        .blue {
            color: blue;
        }
        </style>
      </head>
      <body>
        <div class="blue">
          Hello, world!
        </div>
      </body>
    </html>

    写到这里我必须吐槽一下,css代码直接写在head里和body的元素上,是很不规范的写法,因前面参与的一个华为的项目前端编码很多地方去全都这样子做了,我们维护起来相当费劲,但是现实情况已经这样子了,只能暂且如此了,因此这个办法我个人不是很推荐。

    2、推迟加载CSS

    对于那些首屏渲染不需要用到的CSS,我们可以依旧使用文件形式并在页面内容渲染完成后再加载,当然首频渲染必须要的css文件,肯定还是要放在head里加载的。

    <!doctype html>
    <html>
      <head>
        <style tpe="text/css">
        .blue {
            color: blue;
        }
        </style>
      </head>
      <body>
        <div class="blue">
          Hello, world!
        </div>
        <link href="other.css" rel="stylesheet" />
      </body>
    </html>

    针对这个js脚本文件的引入,我有深入的体会,2016年年初的时候,我们一个交流群的战友发了个截图(非同事),他参与的那个项目,首页上引入了13个js文件,其中不乏jquery,react这些体积相对较大的js库,我当时就懵了,这要是网速不给力,岂不是要哭了,使用依赖加载多好嘛。简简单单多啰嗦了几句,与本文表达的意思无关。希望大家喜欢这篇博文。

  • 相关阅读:
    LeetCode第242题:有效的字母异位词
    commons lang组件介绍和学习
    java中如何将string 转化成long
    java 字符串按小数点分割
    界面优化处理技术之(一)按钮组件优化处理
    系统登陆界面开发及实现之(五)界面版权组件设置
    系统登陆界面开发及实现之(四)界面登录框组件设置
    系统登陆界面开发及实现之(三)界面标题组件设置
    系统登陆界面开发及实现之(二)添加界面背景图片
    转发:base64引起的血案
  • 原文地址:https://www.cnblogs.com/xiangxiao/p/6662439.html
Copyright © 2020-2023  润新知