浏览器工作原理
写在前面
本人对浏览器的工作原理的理解尚浅,如有错误欢迎各位大佬指正。
本文章回答了那些问题
浏览器如何渲染一个页面
浏览器有哪些线程,线程之间如何工作的
为什么要学习这些问题
了解浏览器渲染原理可以帮助我们优化html、css、js的组织,优化渲染性能
了解浏览器进程可以帮助我们深入了解异步编程
浏览器渲染原理
浏览器首先下载html、css、js。 接着解析生成dom tree、rule tree和rendering tree。 再通过layout后渲染页面。
下载
浏览器打开页面之后,会根据页面URL向服务器发送一个请求,服务器响应页面的HTML。
(HTML解析过程中遇到插入的css、和js会同时发起请求资源。)
解析
html/svg 解析生成 dom tree,css 解析生成 css rule tree, 这两者结合生成rendering(render) tree。
渲染树包含多个带有视觉属性(颜色、尺寸等)的矩形, 这些矩形的排列顺序就是它们在屏幕上的显示顺序
解析过程中遇到js标签会下载解析执行
解析的过程是词法分析和语法分析
layout
渲染树构建完成之后进入layout阶段
layout是指计算每个DOM元素最终在屏幕上显示的大小和位置。 遍历顺序为从左至右,从上到下
由于web页面的元素布局是相对的, 所以任意元素的位置发生变化,都会引起其他元素位置的变化,这就是reflow
paint
渲染引擎会遍历渲染树,由用户界面后端层将每个节点绘制出来
按照合理的顺序合并图层然后显示到屏幕上。
浏览器刷新的频率大概是60次/秒, 也就是说刷新一次大概时间为16ms
如果浏览器对每一帧的渲染工作超过了这个时间, 页面的渲染就会出现卡顿的现象。
以上过程是渐进的,并不一定严格按照顺序执行的,为了更快将内容呈现在不屏幕中, 不会等到HTML全部解析完成之后才开始构建渲染树和layout,它会在不断接收和处理其他网络资源的同时,就开始部分内容的解析和渲染
渲染完成之后会触发 ready事件
什么情况下会引起 reflow repaint
当render tree (元素尺寸) 发生变化时则会重新layout 则会因此reflow
浏览器内核
浏览组成
用户界面
浏览器内核: 浏览器引擎(查询操作渲染引擎的接口)、渲染引擎、js引擎、网络(http请求)
数据存储
js引擎 (IE9+: Chakra firefox:monkey chrome:v8)
渲染引擎(firefox:gecko、chrome/safari:webkit)
所以大部分浏览器至少有三个线程:
JS引擎线程、GUI渲染线程、浏览器事件触发线程
除此之外还会有 http请求线程等、计时器线程、EventLoop轮询的处理线程等。
javascript引擎
js引擎是基于事件驱动的, 采用的是单线程运行机制。
因为JS可以操作DOM元素, 从而影响到GUI的渲染结果, 因此JS引擎线程和GUI渲染线程是互斥的。 也就是说
JS引擎处于运行状态时,GUI渲染线程将处于冻结状态。
javascript的单线程
javascript引擎负责解释和执行javascript代码的线程只有一个,称为主线程。js还有其他的线程称为工作线程。
主线程上只执行同步任务。
Web Worker
H5提出了Web Worker标准, 允许js创建多个线程, 但是完全受父线程控制,且不可以操作DOM
工作进程
浏览器还有还有其他的线程,例如:
处理 ajax 的线程,dom事件线程、定时器线程、读写文件的线程等。这些被称为工作进程
这些线程可能存在于js引擎之中或者之外, 称为工作线程
工作线程的任务完成之后, 会推入到一个任务队列(task queue)
JavaScrpt 的异步编程
js引擎只执行同步任务, 异步任务会有工作线程来执行。
异步过程
当需要进行异步操作(定时器、ajax请求、dom事件注册等), 主线程会发一个异步任务的请求, 相应的工作线程接受请求; 当工作线程完成工作之后, 通知主线程;主线程接收到通知之后, 会执行一定的操作(回调函数)。
事件循环
主线程和工作线程之间的通知机制叫做事件循环。
调用栈 (call stack): 主线程执行时生成的调用栈
任务队列 (task queue): 工作线程完成任务后会把消息推到一个任务队列, 消息就是注册时的回调函数
当调用栈为空时, 主线程会从任务队列里取一条消息并放入当前的调用栈当中执行, 主线程会一直重复这个动作直到消息队列为空。 这个过程就叫做事件循环 (event-loop)。
渲染线程和js线程的互斥
渲染线程和js线程是互斥的, 在js引擎执行时,渲染线程会被挂起。
为什么会阻塞
js在浏览器中需要被下载、解释、执行这三部。 html中的script标签是阻塞的, 也就是说顺序下载、解释、执行。
浏览器会在js执行后决定当前文档是否需要进行重新渲染或者重排。
js引擎线程和UI线程是互斥的, 所以js执行时会阻塞页面的渲染。
下载虽然是异步的, 但是执行还是同步的。 先出现的SCRIPT标签一定是先执行。 即使它是最后一个下载完成。
js执行中终端浏览器html解析
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。