浏览器页面--阻塞渲染--场景/优化方案

原文网址:浏览器页面--阻塞渲染--场景/优化方案_IT利刃出鞘的博客-CSDN博客

简介

        本文介绍浏览器的页面的渲染阻塞的场景及其优化方案。

        CSS和JavaScript都会阻塞浏览器的渲染,本文分这两个方面介绍。

CSS阻塞渲染

  • CSS不会阻塞DOM的解析。
    • 原因:HTML的DOM的解析与CSS解析是独立进行的,所以CSS解析不会阻塞DOM的解析。
  • CSS可能会阻塞渲染。
    • 不同的CSS的引入方式结果不同。

详见:浏览器页面--渲染的流程_IT利刃出鞘的博客-CSDN博客

阻塞的场景

style标签中的样式

link引入的样式

解析器

由HTML解析器解析

由CSS解析器解析

是否阻塞DOM解析

是否阻塞渲染

不阻塞浏览器渲染(可能会产生“闪屏现象”)

阻塞浏览器渲染(可以利用这种阻塞避免“闪屏现象”)

是否阻塞JS

为什么不阻塞渲染会引起闪屏呢?

        因为不阻塞渲染就导致CSS很可能在渲染结束后生效,若渲染结束时CSS和后边新生效的CSS不同,那很显然会改变显示效果。

优化方案

CSS阻塞优化方法:尽可能快的提高外部css加载速度

  1. 使用CDN节点进行外部资源加速。
  2. 对css进行压缩(利用打包工具,比如webpack,gulp等,也可以通过开启gzip压缩)。
  3. 减少http请求数,将多个css文件合并或者是干脆直接写成内联样式(内联样式的一个缺点就是不能缓存)。
  4. 优化样式表的代码

JavaScript阻塞渲染

阻塞的场景

JavaScript会阻塞DOM解析、阻塞页面渲染、阻塞后续JS的执行。

1. JS阻塞DOM解析

        浏览器不知道后续脚本的内容,如果先去解析了下面的DOM,而随后的JS删除了后面所有的DOM,那么浏览器就做了无用功,浏览器无法预估脚本里面具体做了什么操作,例如像document.write 这种操作,索性全部停住,等脚本执行完了,浏览器再继续向下解析DOM。    

2. JS阻塞页面渲染

        JS中也可以给DOM设置样式,浏览器同样等该脚本执行完毕,再继续干活,避免做无用功。

3. JS阻塞后续js的执行

        为了维护依赖关系,例如:必须先引入jQuery再引入bootstrap

优化方案

        因为JS会阻塞后续的HTML解析、渲染,所以对JS的阻塞的优化方案大致就是:将JS放到最后、异步执行。

方案1:将JS放到最后

很简单,将script标签放到HTML文件的body标签的最后即可。例如:

<!doctype html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>This is title</title>
</head>

<body>

<div class="container">
    这是个Demo
</div>

<script>
    let name = 'hello'
</script>
</body>
</html>

方案2:defer延迟加载

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

        defer 属性表示延迟执行引入 JavaScript,即 JavaScript 加载时 HTML 不会停止解析,这两个过程是并行的。 整个HTML解析完毕且defer-script也加载完成之后,才会执行所有由defer-script加载的JavaScript代码,再触发 DOMContentLoaded事件。

        defer 不会改变 script 中代码的执行顺序。

        所以,defer 与相比普通 script,有两点区别:

  1. 载入 JavaScript 文件时不阻塞 HTML 的解析。
  2. 执行阶段被放到 HTML 的解析完成之后。

方案3:async异步加载

async异步加载:告诉浏览器不必等到加载完外部文件,可以边渲染边下载,什么时候下载完成什么时候执行。

写法1:标签指定

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

写法2:用js动态创建script元素

<script type="text/javascript">
    (function () {
        var s = document.createElement('script');
        s.type = 'text/javascript';
        s.async = true;            //这句可以删除,默认就是true。
        s.src = 'js/a.js';
        var x = document.getElementsByTagName('script')[0];
        x.parentNode.insertBefore(s, x);
    })();
</script>

这种方法会阻塞onload事件 

写法3: onload事件触发时异步加载

        等html的文件,图片之类的、页面所有的资源全部加载完成后再下载执行js,这样的方法可以避免阻塞onload事件的触发。

(function() {
	function async_load(){
		var s = document.createElement('script');
		s.type = 'text/javascript';
		s.async = true;
		s.src = 'js/yibujiaz.js';
		var x = document.getElementsByTagName('script')[0];
		x.parentNode.insertBefore(s, x);
	}
	if (window.attachEvent){
		window.attachEvent('onload', async_load);
	} else {
		window.addEventListener('load', async_load, false);
	}
})();

补充内容

CSS与JS

        CSS的解析和JS的执行是互斥的(互相排斥),CSS解析的时候JS停止执行,JS执行的时候CSS停止解析。

不会阻塞外部资源

        CSS阻塞和JS阻塞都不会阻塞浏览器加载外部资源(图片、视频、样式、脚本等)。

        原因:浏览器始终处于一种:“先把请求发出去” 的工作模式,只要是涉及到网络请求的内容,无论是:图片、样式、脚本,都会先发送请求去获取资源,至于资源到本地之后什么时候用,由浏览器自己协调。这种做法效率很高。

预解析

        WebKit 和 Firefox 都进行了预解析这项优化。在执行js脚本时,浏览器的其他线程会解析文档的其余部分,找出并加载需要通过网络加载的其他资源。通过这种方式,资源可以在并行连接上加载,从而提高总体速度。请注意,预解析器不会修改 DOM 树。

其他网址

浏览器渲染之阻塞渲染_EWJRQKJRQ的博客-CSDN博客_渲染阻塞

浏览器渲染CSS阻塞、JS阻塞_ColdCoder的博客-CSDN博客

页面渲染时js阻塞的解决方法_weixin_30456039的博客-CSDN博客

  • 29
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT利刃出鞘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值