最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • CSS、JS 对页面加载与交互的影响

    正文概述 掘金(西行无归)   2021-02-07   445

    一、CSS 的加载对 HTML 的解析及页面呈现有怎样的影响呢

    实验一:

    实验代码如下:

    HTML 代码:

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8" />
        <title>实验一</title>
        <link rel="stylesheet" type="text/css" href="http://127.0.0.1:3000/test1.css" />
      </head>
      <body>
        <div id="box0">0</div>
        <div id="box1">1</div>
      </body>
    </html>
    

    CSS 代码:

    #box0 {
      color: red;
    }
    
    #box1 {
      color: green;
    }
    

    Node 代码如下:

    const http = require('http');
    const fs = require('fs');
    
    const hostname = '127.0.0.1';
    const port = 3000;
    
    const server = http.createServer((req, res) => {
      if(req.url === '/test1.css') {
        fs.readFile('test1.css', 'utf8' , (err, data) => {
          if (err) {
            console.error(err);
            res.statusCode = 500;
            res.end('');
            return;
          }
          setTimeout(() => {
            res.statusCode = 200
            res.setHeader('Content-Type', 'text/css')
            res.end(data);
          }, 10000);
        })
      }
    });
    
    server.listen(port, hostname, () => {
      console.log(`服务器运行在 http://${hostname}:${port}/`)
    });
    

    代码的思路是在 head 标签中,放入 link 标签,并且让 CSS 文件的请求接口,在 10s 后返回,观察 CSS 的加载对 HTML 的解析及页面呈现的影响。

    实验现象:请求页面后,过了大约 10s,页面才呈现,我们可以得出结论,在 head 标签中,请求 CSS 文件,CSS 的加载会阻塞页面的呈现,那么 CSS 的加载会阻塞 HTML 的解析吗,我们可以通过 Performance 进行分析。

    实验结果图一:

    CSS、JS 对页面加载与交互的影响

    实验结果图二:

    CSS、JS 对页面加载与交互的影响

    从图一中可以看出在 56ms 左右的时候,发生了 DOMContentLoaded 事件,说明 HTML 已经解析完成,这时候 CSS 文件还在加载,说明,在 head 标签中,CSS 的加载,不会阻塞 HTML 的解析。MDN 上对 DOMContentLoaded 与 Onload 事件的解释为:

    从图二中可以看出,在 10s 左右,CSS 加载完成,触发 Onload 事件,然后进行了样式计算、布局、绘制、合成图层等过程。图中还显示了 FCP 和 LCF 发生的时间点,FCP 为 First Contentful Paint,表示页面开始绘制的时间点,LCP 为 Largest Content Paint,表示首屏绘制完成的时间点。图二说明页面确实是在 10s 左右呈现,与现象相吻合。

    实验一结论:head 标签中加载 CSS,不会阻塞 HTML 的解析,但是会阻塞首屏呈现。

    实验二:

    HTML 代码:

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8" />
        <title>实验二</title>
      </head>
      <body>
        <div id="box0">0</div>
        <link rel="stylesheet" type="text/css" href="http://127.0.0.1:3000/test1.css" />
        <div id="box1">1</div>
      </body>
    </html>
    

    CSS 代码同实验一

    Node 代码同实验一

    代码思路,将 link 标签放在 2 个 div 标签之间,CSS 资源 10s 后返回,观察 CSS 资源的加载对 2 个 div 标签呈现的影响。

    实验现象,加载页面后,id 为 box0 的标签立即呈现,但是颜色为黑色,10s 后,box0 变为红色,box1 的标签呈现,并且为绿色。从实验显现可以知道,在 body 标签中加载 CSS 资源,CSS 资源的加载,会阻塞 link 标签后面标签的呈现,但是不会阻塞 link 标签前面标签的呈现。更具体的分析与结论,我们通过 Performance 得出。

    实验结果图三:

    CSS、JS 对页面加载与交互的影响

    实验结果图四:

    CSS、JS 对页面加载与交互的影响

    从图三可以看出,页面加载,即开始 HTML 的解析,在 107ms 左右,进行首次渲染,然后继续 CSS 的加载,在 10s 左右,CSS 加载完成,然后解析样式,继续解析 HTML,然后发生 DOMContentLoaded 事件,HTML 解析完成,进行布局、合成图层等过程,页面最终样子呈现。从这个过程可以看出,当解析到 body 中的 link 标签时,HTML 的解析过程会被打断(已经被解析的 HTML 标签,可以立即呈现,但是没有样式),一直到 CSS 资源加载、解析完成后,HTML 继续解析,HTML 解析完成后,进行样式计算,布局等过程,页面最终样子呈现。

    实验二结论:如果 link 标签放在 body 标签底部,这样 CSS 资源的加载,不会阻塞页面内容的呈现,但是页面没有样式,等 CSS 加载完毕后,页面内容才会有样式,从页面无样式到有样式,会发生一次跳动,对用户体验也不好,所以,把 link 标签放在 head 中,等样式文件和 HTML 都解析完成后,直接给用户展示最终样子的页面,用户体验应该更好些。另外,在我们知道,通过 Performance 也可以看出,渲染进程中,有主线程、合成线程等线程,其中主线程上进行 HTML 解析、CSS 解析、样式计算、JS 编译执行、JS 的垃圾回收等过程,但是线程一次只能执行一个任务,执行了 HTML 解析,就不能进行 CSS 解析等其他操作,所以这些过程肯定是相互阻塞的,重点就是怎么在主线程上合理分配这些过程,使得对用户体验好。

    二、JS 的加载与解析执行对 HTML 的解析及页面呈现有怎样的影响呢

    实验三:

    实验代码如下:

    HTML 代码:

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8" />
        <title>实验三</title>
        <script type="text/javascript">
          function sleep(time) {
            const endTime = new Date().getTime() + time;
            while(new Date().getTime() < endTime) {}
          }
    
          sleep(10000);
        </script>
      </head>
      <body>
        <div id="box0">0</div>
        <div id="box1">1</div>
      </body>
    </html>
    

    代码思路,在 head 标签中放入 JS 内联脚本,脚本执行时长大概为 10s,看下 JS 的执行是否会阻塞 HTML 的解析与页面呈现。

    实验现象,加载页面后,大约过了 10s,页面才呈现,可以看出 JS 的解析执行,是会阻塞页面的呈现。下面通过 Performance 得出更具体的结论。

    实验结果图五:

    CSS、JS 对页面加载与交互的影响

    实验结果图六:

    CSS、JS 对页面加载与交互的影响

    实验结果图七:

    CSS、JS 对页面加载与交互的影响

    从图五、六、七,可以看出,加载页面后,首先解析 HTML,然后碰到 script 标签,中断 HTML 的解析,然后编译执行 JS,等 JS 执行完后,继续解析 HTML,最后呈现页面,所以放在 head 标签中的内联脚本会阻塞 HTML 的解析与页面的呈现。

    实验四:

    实验代码如下:

    HTML 代码:

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8" />
        <title>实验四</title>
      </head>
      <body>
        <div id="box0">0</div>
        <script type="text/javascript">
          function sleep(time) {
            const endTime = new Date().getTime() + time;
            while(new Date().getTime() < endTime) {}
          }
    
          sleep(10000);
        </script>
        <div id="box1">1</div>
      </body>
    </html>
    

    代码思路,在 body 标签中放入 JS 内联脚本,脚本执行时长大概为 10s,看下 JS 的执行是否会阻塞 HTML 的解析与页面呈现。

    实验现象,加载页面后,大约过了 10s,页面才呈现,可以看出 JS 的解析执行,是会阻塞页面的呈现。实验四与实验三的 Performance 图基本一样,所以,我感觉内联脚本放在 head 或者 body 标签中的效果是一样的,都是解析到 script 标签后,中断 HTML 的解析,开始编译执行 JS,等 JS 执行完后,继续解析 HTML,最后呈现页面。

    实验五:

    实验代码如下:

    HTML 代码:

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8" />
        <title>实验五</title>
        <script type="text/javascript" src="http://127.0.0.1:3000/test1.js"></script>
      </head>
      <body>
        <div id="box0">0</div>
        <div id="box1">1</div>
      </body>
    </html>
    

    Node 代码如下:

    const http = require('http');
    const fs = require('fs');
    
    const hostname = '127.0.0.1';
    const port = 3000;
    
    const server = http.createServer((req, res) => {
      if(req.url === '/test1.js') {
        setTimeout(() => {
          res.statusCode = 200
          res.setHeader('Content-Type', 'text/javascript')
          res.end(`console.log('西行无归')`);
        }, 10000);
      }
    });
    
    server.listen(port, hostname, () => {
      console.log(`服务器运行在 http://${hostname}:${port}/`)
    });
    

    代码的思路是在 head 标签中,放入 script 标签,并且让 JS 文件的请求接口,在 10s 后返回,观察 JS 的加载对 HTML 的解析及页面呈现的影响。

    实验现象:请求页面后,过了大约 10s,页面才呈现,我们可以得出结论,在 head 标签中,请求 JS 文件,JS 的加载会阻塞页面的呈现,那么 JS 的加载会阻塞 HTML 的解析吗,我们可以通过 Performance 进行分析。

    实验结果图八:

    CSS、JS 对页面加载与交互的影响

    实验结果图九:

    CSS、JS 对页面加载与交互的影响

    从图八和图九中可以看出,加载页面后,开始开始解析 HTML,当解析到 script 标签时,停止 HTML 解析,等待 JS 文件的加载,10s 左右,JS 加载结束,编译执行 JS,然后继续解析 HTML,HTML 解析结束后,发生 DOMContentLoaded 事件,最后发生合成图层过程,页面呈现。

    所以,放在 head 标签中的外部脚本,会阻塞 HTML 的解析,HTML 都被解析了,body 标签自然没有被解析,没有可呈现 DOM 元素,页面自然是一片空白。

    实验六:

    实验代码如下:

    HTML 代码:

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8" />
        <title>实验六</title>
      </head>
      <body>
        <div id="box0">0</div>
        <script type="text/javascript" src="http://127.0.0.1:3000/test1.js"></script>
        <div id="box1">1</div>
      </body>
    </html>
    

    Node 代码同实验五

    代码的思路是在 body 标签中,放入 script 标签,并且让 JS 文件的请求接口,在 10s 后返回,观察 JS 的加载对 HTML 的解析及页面呈现的影响。

    实验现象:请求页面后,id 为 box0 的 div 标签呈现,过了大约 10s,id 为 box1 的 div 标签呈现,下面我们通过 Performance 看下更具体的情况。

    实验结果图十:

    CSS、JS 对页面加载与交互的影响

    实验结果图十一:

    CSS、JS 对页面加载与交互的影响

    从图十和图十一中可以看出,加载页面后,开始开始解析 HTML,当解析到 script 标签时,停止 HTML 解析,等待 JS 文件的加载,但是在 58ms 左右,页面进行了渲染,10s 左右,JS 加载结束,编译执行 JS,然后继续解析 HTML,HTML 解析结束后,发生 DOMContentLoaded 事件,最后发生合成图层过程,页面呈现。

    所以,放在 body 标签中的外部脚本,会阻塞 HTML 的解析,但是已解析的标签可以呈现在页面上。

    对于外部 JS,script 标签还可以加上 defer 或 async 属性。defer 在 MDN 上的解释为:

    这段话的意思是,对于外部脚本,如果 script 标签上有 defer 属性,那么 HTML 的解析与页面呈现不会被 script 标签打断。如果多个 script 标签有 defer 属性,不管哪个脚本先加载完,JS 的执行顺序由 script 标签的顺序决定。

    对于 async,MDN 上的解释为:

    对于 async 有 3 个特点,加了 asnyc 的脚本的第一个特点是,不阻塞 HTML 的解析与页面的呈现,这个特点和 defer 是一样的,不同的是,defer 脚本的编译执行一定在 DOMContentLoaded 之前,async 脚本的编译执行一定在 Onload 之前,这是 async 脚本的第二个特点,async 脚本的第三个特点是,多个 async 脚本的执行顺序是随机的,谁先下载完,谁先执行,下面通过一个实验,说明 async 的第一个和第二个特点。

    实验七:

    实验代码如下:

    HTML 代码:

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8" />
        <title>实验七</title>
        <script async type="text/javascript" src="http://127.0.0.1:3000/test1.js"></script>
      </head>
      <body>
        <div id='0'>0</div>
        <div id='1'>1</div>
        <!-- 中间省略了 2996 个 div 标签 -->
        <div id='998'>998</div>
        <div id='2999'>999</div>
      </body>
    </html>
    

    JS 代码:

    function sleep(time) {
      const endTime = new Date().getTime() + time;
      while(new Date().getTime() < endTime) {}
    }
    
    sleep(10000);
    

    Node 代码如下:

    const http = require('http');
    const fs = require('fs');
    
    const hostname = '127.0.0.1';
    const port = 3000;
    
    const server = http.createServer((req, res) => {
      if(req.url === '/test1.js') {
        fs.readFile('test1.js', 'utf8' , (err, data) => {
          if (err) {
            console.error(err);
            res.statusCode = 500;
            res.end('');
            return;
          }
          
          res.statusCode = 200
          res.setHeader('Content-Type', 'text/css')
          res.end(data);
          return;
        })
      }
        
    });
    
    server.listen(port, hostname, () => {
      console.log(`服务器运行在 http://${hostname}:${port}/`)
    });
    

    代码的思路是,解析一个很大的 HTML 文件,然后立即请求一个带 async 属性的 JS 文件,但是 JS 的执行时间为 10s,看下 JS 下载完后,是否会阻塞 HTML 解析与页面的呈现。

    下面通过 Performance 来说明 async 脚本的前两个特点:

    实验结果图十二:

    CSS、JS 对页面加载与交互的影响

    实验结果图十三:

    CSS、JS 对页面加载与交互的影响

    从图十二和图十三可以看出,加了 async 标签的 JS,加载不会阻塞 HTML 的解析和页面的呈现,JS 的编译执行也是放在了 HTML 解析结束和页面呈现之后,和 defer 脚本一样,只不过 async 脚本完成编译执行是在 Onload 事件之前。

    三、CSS 与 JS 之间的相互影响

    上面我们分别分析了 CSS 与 JS 对 HTML 解析与页面呈现的影响,那一个 HTML 文件中,同时包含 CSS 与 JS,情况会是怎样的呢,有了前面 7 个实验的基础,让我们来分析下面几种情况,HTML 解析与页面呈现的过程吧。

    情况一:

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8" />
        <title>测试 1</title>
        <!-- JS 的加载时间为 10s,编译执行时间可忽略不计 -->
        <script type="text/javascript" src="http://127.0.0.1:3000/test1.js"></script>
        <!-- CSS 的加载时间为 5s,解析时间可忽略不计 -->
        <link rel="stylesheet" type="text/css" href="http://127.0.0.1:3000/test1.css" />
      </head>
      <body>
        <div id="box0">0</div>
        <div id="box1">1</div>
      </body>
    </html>
    

    上面代码,HTML 解析与页面呈现的情况是怎样的呢,其中 JS 的加载时间为 10s,编译执行时间可忽略不计,CSS 的加载时间为 5s,解析时间可忽略不计。让我们一起来分析下吧。

    首先开始解析 HTML,发现 script 和 link 标签,开始下载 JS 和 CSS,JS 在 10s 左右加载完毕,CSS 在 5s 左右加载完毕,但是 script 标签会阻塞 HTML 的解析,所以虽然 CSS 资源提前下载好了,也不会解析 CSS,等到 10s 时,JS 加载好后,JS 编译执行,然后接着解析 HTML,看到 link 标签,解析 CSS,然后接着解析 HTML,然后计算样式、布局,最后页面呈现(上述分析已做实验验证)。

    情况二:

    HTML 代码:

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8" />
        <title>测试 2</title>
        <!-- CSS 的加载时间为 10s,解析时间可忽略不计 -->
        <link rel="stylesheet" type="text/css" href="http://127.0.0.1:3000/test1.css" />
      </head>
      <body>
        <div id="box0">0</div>
        <!-- JS 的加载时间为 5s,编译执行时间可忽略不计 -->
        <script type="text/javascript" src="http://127.0.0.1:3000/test1.js"></script>
        <div id="box1">1</div>
      </body>
    </html>
    

    上面代码 CSS 的加载时间为 10s,JS 的加载时间为 5s。

    首先开始解析 HTML,发现 link 和 script 标签,去加载 CSS 与 JS 资源,CSS 在 10s 左右加载完毕,JS 在 5s 左右加载完毕,由实验一可知,CSS 的加载不会阻塞 HTML 的解析,但是会阻塞页面的首次渲染,所以解析完 link 标签后,接着解析 HTML,当解析到 script 标签时,由前面实验可知,JS 的加载和执行会阻塞 HTML 的渲染,所以 HTML 解析暂停,等待 JS 下载,5s 左右时,JS 加载完后,JS 本应该开始执行,但是 script 标签前面有 link 标签, JS 是有访问 DOM 元素 style 属性的能力的,所以,JS 的执行,要等到 CSS 解析完毕,这时候,情况变为:CSS 的加载阻塞 JS 的执行,JS 的执行阻塞 HTML 的解析,在 10s 左右,CSS 现在完毕,开始解析 CSS,CSS 解析完毕后,开始编译执行 JS,JS 执行完毕后,接着解析 HTML,然后样式计算、布局、更新图层树、绘制、合成图层,呈现页面。

    四、总结

    本文通过实验的方式,分析了 CSS 与 JS 对 HTML 解析与页面呈现的影响,希望能在我们以后的工作中,起到一定的指导作用,但是现实情况是多变的,重点还是要自己做实验,自己得出的结论,才记忆深刻,自己探索,除了能获取一个结果外,还能收获更更要的东西。通过实验,我们知道 head 标签中的 link 标签,会阻塞页面的渲染,这是合理的,因为,我们想给用户直接呈现有样式的页面,但是我们依然是有些措施是去减少 link 阻塞页面渲染的时间的。本文的标题是 CSS、JS 对页面加载与交互的影响,本文只讨论了 CSS、JS 对页面加载的影响,对交互的影响还没有讨论,由于快放假了,我手头上还有些工作没有收尾,要赶紧收尾了,交互这部分暂时没时间写了,所以这部分的内容放在节后更新。页面的渲染过程为:解析 HTML、解析 CSS、计算样式、布局、分层、绘制、分块、栅格化、合成图层,我们优化交互,其实就是减少渲染过程的流水线。

    五、更新日志

    2021-02-06: 发布
    

    起源地下载网 » CSS、JS 对页面加载与交互的影响

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元