浏览器渲染引擎执行机制--DOM树渲染

本文详细解析了浏览器渲染引擎在处理DOM树渲染时的行为,包括src和href的区别、link和script标签的加载顺序,以及defer和async属性对脚本加载的影响。理解这些机制有助于优化页面加载性能,减少JavaScript对页面渲染的阻塞。建议将脚本放在页面底部,并根据需要使用defer或async属性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

src和href的区别?

link标签加载顺序?

script标签加载顺序?

defer和async?

想弄懂以上问题,先来了解一下DOM树渲染原理

DOM文档的加载顺序是由上而下的顺序加载;

1、DOM加载到link标签(css)

css文件的加载是与DOM的加载并行的,也就是说,css在加载时Dom还在继续加载构建,而过程中遇到的css样式或者img,则会向服务器发送一个请求,待资源返回后,将其添加到dom中的相对应位置中;

浏览器一边下载HTML网页,一边开始解析;

解析过程中,发现link 标签

浏览器继续往下解析HTML网页,同时并行下载link标签中的css样式

2、DOM加载到script标签(js)

(1)正常非处理网页

由于js文件不会与DOM并行加载,因此需要等待js整个文件加载完之后才能继续DOM的加载,倘若js脚本文件过大,则可能导致浏览器页面显示滞后,出现“假死”状态,这种效应称之为“阻塞效应”;会导致出现非常不好的用户体验;

正常的网页加载流程是这样的。

浏览器一边下载HTML网页,一边开始解析

解析过程中,发现script标签

暂停解析,网页渲染的控制权转交给JavaScript引擎32

如果script标签引用了外部脚本,就下载该脚本,否则就直接执行

执行完毕,控制权交还渲染引擎,恢复往下解析HTML网页

html需要等head中所有的js和css加载完成后才会开始绘制,但是html不需要等待放在body最后的js下载执行就会开始绘制,因此将js放在body的最后面,可以避免资源阻塞,同时使静态的html页面迅速显示。将脚本文件都放在网页尾部加载,还有一个好处。在DOM结构生成之前就调用DOM,JavaScript会报错,如果脚本都在网页尾部加载,就不存在这个问题,因为这时DOM肯定已经生成了。

js文件不会与DOM并行加载,而这个特性也是为什么在js文件中开头需要$(document).ready(function(){})或者(function(){})或者window.onload,即是让DOM文档加载完成之后才执行js文件,这样才不会出现查找不到DOM节点等问题;

js阻塞其他资源的加载的原因是:浏览器为了防止js修改DOM树,需要重新构建DOM树的情况出现;

(2)外链的js如果含有defer="true"属性,将会并行加载js,到页面全部加载完成后才会执行,会按顺序执行。

defer属性的作用是,告诉浏览器,等到DOM加载完成后,再执行指定脚本。

浏览器开始解析HTML网页

解析过程中,发现带有defer属性的script标签

浏览器继续往下解析HTML网页,同时并行下载script标签中的外部脚本 浏览器完成解析HTML网页,此时再执行下载的脚本

对于内置而不是连接外部脚本的script标签,以及动态生成的script标签,defer属性不起作用。

(3)外链的js如果含有async="true"属性,将不会依赖于任何js和css的执行,此js下载完成后立刻执行,不保证按照书写的顺序执行。因为async="true"属性会告诉浏览器,js不会修改dom和样式,故不必依赖其它的js和css。

async属性的作用是,使用另一个进程下载脚本,下载时不会阻塞渲染。

浏览器开始解析HTML网页

解析过程中,发现带有async属性的script标签

浏览器继续往下解析HTML网页,同时并行下载script标签中的外部脚本 脚本下载完成,浏览器暂停解析HTML网页,开始执行下载的脚本

脚本执行完毕,浏览器恢复解析HTML网页

async属性可以保证脚本下载的同时,浏览器继续渲染。需要注意的是,一旦采用这个属性,就无法保证脚本的执行顺序。哪个脚本先下载结束,就先执行那个脚本。另外,使用async属性的脚本文件中,不应该使用document.write方法。

一般来说,如果脚本之间没有依赖关系,就使用async属性,如果脚本之间有依赖关系,就使用defer属性。如果同时使用async和defer属性,后者不起作用,浏览器行为由async属性决定。

同时使用defer和async属性时,defer属性会失效;

解答:

src和href的区别

两者用来引用外部资源

src:资源的引入。将资源加载到页面中去

src资源加载完成才会执行后续。 img、script

href:超文本的引用。简历当前元素与当前文档之间的链接

href资源加载并行进行,不会停止加载其它资源。  a 、link

 link标签

 继续解析dom文档, 并行加载css资源,多个link顺序执行,层叠覆盖

 script标签加载顺序

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

    没有 defer 或 async,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该 script 标签之下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行。多个script按顺序加载并执行

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

    有 async,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。多个script按顺序加载,加载结束立即执行,无法保证顺序执行

  3. <script defer src="myscript.js"></script>

    有 defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。多个script按顺序加载并执行

 script标签位置

Javascript的加载和执行的特点: 
(1)载入后马上执行; 

(2)执行时会阻塞页面后续的内容(包括页面的渲染、其它资源的下载)。原因:因为浏览器需要一个稳定的DOM树结构,而JS中很有可能有 代码直接改变了DOM树结构,比如使用 document.write 或 appendChild,甚至是直接使用的location.href进行跳转,浏览器为了防止出现JS修 改DOM树,需要重新构建DOM树的情况,所以 就会阻塞其他的下载和呈现。

减少 JavaScript 对性能的影响的方法:

  1. 将所有的script标签放到页面底部,也就是body闭合标签之前,这能确保在脚本执行前页面已经完成了DOM树渲染。
  2. 尽可能地合并脚本。页面中的script标签越少,加载也就越快,响应也越迅速。无论是外链脚本还是内嵌脚本都是如此。
  3. 采用无阻塞下载 JavaScript 脚本的方法: 
    (1)使用script标签的 defer 属性(仅适用于 IE 和 Firefox 3.5 以上版本); 
    (2)使用动态创建的script元素来下载并执行代码;

 defer和async的区别

defer和async是script标签的两个属性,用于在不阻塞页面文档解析的前提下,控制脚本的下载和执行,是js延迟加载的两种方式

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

    没有 defer 或 async,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该 script 标签之下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行。

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

    有 async,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。

  3. <script defer src="myscript.js"></script>

    有 defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成请输入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值