简介:在地址栏输入一个网址,浏览器如何渲染,渲染的顺序是什么,本文主要讲解这个概念,方便大家在面试过程如何回答
首先在浏览器输入一个地址,会有以下步骤:
1、浏览器查找域名对应的IP
(1) 浏览器搜索自己的DNS缓存;
(2) 搜索操作系统中的DNS缓存;
(3) 操作系统向它的本地DNS服务器(LDNS)发送一个DNS查询报文(包含需要被转换的主机名),LDNS查询自己的DNS缓存,若查找失败则发起一个迭代DNS解析请求进行分级查询:
a. 由于根域名服务器的NS记录和IP记录一般不会变化,所以内置在DNS服务器中,本地DNS服务器将报文转发到所有的根域名服务器,询问顶级域名服务器的NS记录,最先回复的根域名服务器被缓存,以后只向这台服务器发送请求, 根域名服务器向本地DNS服务器返回对应的顶级域名服务器的NS记录和IP记录列表;
b. 本地DNS服务器向这些所有TLD服务器(顶级域名服务器)发送查询报文,TLD服务器以次级域名服务器的NS记录及其IP地址作为响应;
c. 本地DNS服务器向这些所有SLD服务器(次级域名服务器)发送查询报文,SLD服务器以主机名的IP地址作为响应。
(4) LDNS将得到的IP地址返回给操作系统,同时自己也将IP缓存起来;
(5) 操作系统将IP地址返回给浏览器,同时自己也将IP缓存起来;
(6) 至此,浏览器已经得到了域名对应的IP。
备注:
1、在一个请求链中,当某DNS服务器接收到一个DNS回答时,它能将该回答中的信息缓存在本地存储器中
2、每一级域名都有自己的NS记录,NS记录指向该级域名的域名服务器。这些服务器知道下一级域名的各种记录。所谓"分级查询",就是从根域名开始,依次查询每一级域名的NS记录,直到查到最终的IP地址
3、主机名.次级域名.顶级域名.根域名 对应 host.sld.tld.root,根域名.root对于所有域名都是一样的,所以平时是省略的,主机名也称三级域名
4、根域名下有子域,才有顶级域名;顶级域名下有子域,才有对应的次级域名;次级域名下有主机,才有主机名)
2、建立TCP连接(三次握手)
(1)客户端向IP地址对应的服务器发送一个建立连接的请求
(2)服务器接到请求后发送同意连接的信号
(3)客户端接到同意连接的信号后,再次向服务器发送确认信号,至此,客户端和服务器建立了连接
备注:在客户和服务器上分别有一个套接字与该连接相关联,客户端和服务器进程就可以通过套接字接口(socket,进程通过套接字接口向网络发送报文和从网络接收报文)访问TCP
3、发送HTTP请求
(1)浏览器根据URL内容生成HTTP请求,请求中包含文件的位置、请求的方式、请求中客户端向服务端传递的数据、请求的一些附加信息等,浏览器向该服务器发送一个HTTP请求报文;
(2)服务器接到请求后,从其中的存储器(内存或磁盘)检索出对象并封装到HTTP响应报文,向客户发送HTTP响应报文,若请求成功,响应报文中会包含客户端请求的HTML文件;
4、浏览器解析并渲染页面
浏览器边解析边渲染。首先浏览器解析HTML文件构建DOM树,解析CSS文件构建CSSOM树,接着在DOM树和CSSOM树的基础上构建渲染树,一旦渲染树构建完成,浏览器就开始布局和显示(绘制‘paint’)页面元素。
若解析过程中,需要请求外部资源如图像、JS文件等,除了JS文件,浏览器将异步发送HTTP请求以获得相应资源,不会影响HTML文档进行加载,若是JS文件,HTML会挂起渲染过程,等到重新请求获得的JS文件加载完毕并解析执行完毕后,才会继续HTML的渲染,JS的解析由浏览器的JS解析引擎完成(涉及JS的单线程运行特性和事件循环执行机制:一个主线程+一个任务队列)
5、断开连接(四次挥手)
(1)主机向服务器发送断开连接的请求(断开)
(2)服务器发送确认收到请求的信号(确认)
(3)服务器向主机发送断开通知(断开)
(4)主机接到断开通知后断开连接并反馈一个确认信号,服务器收到确认信号后断开连接(确认)
在加载的过程中主要的加载顺序如下几点:
当浏览器获得一个html文件, 会"自上而下"加载, 并在加载过程中进行解析渲染. 下载和渲染是同时进行的。
在渲染到页面的某一部分时, 其上面到所有部分都已经下载完成(并不是说所有关联元素都已经下载完)。
如果加载过程中遇到外部css文件, 浏览器会发出一个请求, 来获取css文件. 。
样式表在下载完成后, 将和以前下载的所有样式表一起进行解析, 解析完成后, 将对此前所有元素(含以前已经渲染的)重新进行渲染。
遇到图片资源, 浏览器会发出请求获取图片资源. 这是异步请求, 并不会影响html文档进行加载,。
当文档加载过程中遇到js文件, html文档会挂起渲染(加载解析渲染同步)的线程, 不仅要等待文档中js文件加载完毕, 还要等待解析执行完毕, 才可以恢复html文档的渲染线程. 即js的加载不能并行下载和解析。
原因: js有可能会修改DOM, 比如document.write. 这意味着, 在js执行完成前, 后续所有资源的下载可能是没有必要的, 这是js阻塞后续资源下载的根本原因.。
所以一般将外部引用的js文件放在</body>前。
虽然css文件的加载不影响js文件的加载,但是却影响js文件的执行, 即使js文件内只有一行代码, 也会造成阻塞 。
原因: 可能会有: var width = $('#id').width(). 这意味着, 在js代码执行前, 浏览器必须保证css文件已下载和解析完成。这也是css阻塞后续js的根本原因。
办法:当js文件不需要依赖css文件时,可以将js文件放在头部css的前面。
当然除了,<link href="" />这种形式,内部<style></style>这种样式定义,在考虑阻塞时也要考虑js,css中如果有重定义, 后定义函数将覆盖前定义函数。
在渲染过程中主要的解析过程:
浏览器解析html代码, 创建一棵DOM树。
浏览器解析CSS代码, 创建CSSOM树(CSS Object Model)。
CSSOM树是附在DOM结构上的样式的一种表示方式,与DOM树的呈现方式一样,只是每个节点都带上样式,包括明确定义的和隐式继承的;CSS是一种渲染阻塞资源,需要解析完毕后才能进入生成渲染树的环节,CSS并不像HTML能够执行部分并显示,因为CSS具有继承属性,后面定义的样式会覆盖或修改前面的样式。所以CSS也会阻塞脚本。
JavaScript解析并执行。
构建DOM树和CSSOM树后,下一步就是构建一棵渲染树(rendering tree)。
DOM树完全与html标签一一对应, 但是渲染树会忽略掉不需要渲染的元素, 比如head, display: none的元素等
生成布局,基于HTML页面的meta viewport标签生成布局。
绘制。
对浏览器内核的理解:
浏览器内核主要分成两部分:渲染引擎和js引擎。最开始渲染引擎和JS引擎并没有区分的很明确,后来JS引擎越来越独立,内核就倾向于只指渲染引擎。
渲染引擎(The rendering engine):
职责就是渲染,即在浏览器窗口中显示所请求的内容。默认情况下,渲染引擎可以显示html、xml文档及图片,也可以借助插件显示一些其他类型的数据,比如使用PDF阅读器插件可以显示PDF格式数据。
渲染主流程:
渲染引擎获得所请求的文档后 => 解析html以构建DOM树 => 加载并加息CSS,构建CSSOM树 => 构建render树 => 布局render树 => 绘制render树
详细过程:
渲染引擎开始解析html,并将标签转化为内容树中的DOM节点,接着解析CSS文件或者style中的样式,构建CSSOM树,CSSOM树以及DOM中的可见性指令将被用来构建另一棵树,即render树,Render树由一些包含有颜色和大小等属性的矩形组成,它们将被按照正确的顺序显示到屏幕上。Render树构建好了之后,将会执行布局过程,它将确定每个节点在屏幕上的确切坐标。再下一步就是绘制,即遍历render树,并使用UI后端层绘制每个节点。
JS引擎:解析和执行javascript来实现网页的动态效果。
原文链接:https://www.teaspect.com/detail/5546
更多前端面试基础内容:
前端面试题-http状态码,html标签语义化,应用seo-第三部分