一、学习目标:
1、浏览器有哪些主要内核?
2、浏览器核心组成部分有哪些?
3、浏览器是多线程应用程序还是单线程应用程序?有哪些核心进程?
4、哪些操作会阻塞浏览器渲染?
5、样式在head中引入和body中有什么区别?
6、如何通过工具分析资源的加载,解析,渲染性能?
7、资源加载是否有优先级?是怎么样划分的?
二、浏览器组成原理:
1、浏览器内核及js引擎分类:
a)、浏览器的占比图:
b)、分类表:
浏览器名称 | 内核 | js引擎 |
---|---|---|
IE | Trident | JScript(IE3.0-IE8.0) / Chakra(IE9+之后,查克拉) |
FireFox | Gecko | SpiderMonkey(1.0-3.0)/ TraceMonkey(3.5-3.6)/ JaegerMonkey(4.0-) |
Google Chrome | Webkit->Blink | V8 |
Safari | Webkit | JavaScriptCore(-3.1)/ SquirrelFish(4-) |
Opera | 最初是Presto,后来是Webkit,现在是Blink | Linear A(4.0-6.1)/ Linear B(7.0-9.2)/ Futhark(9.5-10.2)/ Carakan(10.5-) |
2、组成部分:
现在浏览器分为shell
和内核
两部分,其中shell的种类相对比较多,内核则比较少。
shell是浏览器外壳
:主要是提供给用户界面操作,参数设置等并驱动内核实现各种功能。例如菜单、地址栏、后退/前进按钮、书签目录等。内核是浏览器核心
:内核是基于标记语言显示内容的程序或模块。随着JS引擎越来越独立,内核就倾向于只指渲染引擎
。
结构图如下:
解释说明:
- user interface(用户界面):包括菜单、地址栏、后退/前进按钮、书签目录等。(通俗的说:除了显示页面内容之外的部分)。
- browser engine(浏览器引擎):是多线程,在用户界面和呈现引擎之间传送指令。(通俗的说:用来查询及操作和调用渲染引擎接口)。
- rendering engine(渲染引擎): 用来显示请求的内容,例如,如果请求内容为html,它负责解析html及css,并将解析后的结果显示出来。
- network layer(网络层):用来完成网络调用,(页面的请求就是通过网络层获取的),比如 HTTP 请求。其接口与平台无关并为所有平台提供底层实现 。
- JS engine(JS引擎 比如 V8):用来解释执行JS代码。
- UI backend(UI后端):用来绘制类似组合选择框及对话框等基本组件,不特定于某平台的通用接口,底层使用操作系统的用户接口。
- data persistence(数据存储): 属于持久层,浏览器需要在硬盘中保存类似cookie的各种数据,HTML5定义了web database技术,这是一种轻量级完整的客户端存储技术。
对于进程和线程的说法:
- 浏览器引擎是多线程的,它是所有线程的父线程,并对所有的子线程进行管理和调度。
- js引擎是单线程的,只有一个线程执行任务。
- 打开一个tag页面,他们之间是有共享资源,也有独立资源。独立资源:rendering engine,JS engine;共享资源:user interface,browser engine,network layer,UI backend,data persistence。
- 进程之间是可以通过post message进行通信。
3、工作流程:
解释说明:
-
打开浏览器或打开新的tab页,就会创建 独立资源:rendering engine,JS engine;共享资源:user interface,browser engine,network layer,UI backend,data persistence。
-
browser engine会调用network layer,发送一个网络请求,从而请求服务端的html页面。
-
返回html之后,就会对html进行预编译,从中提取出js,css,图片,视频,音频等静态资源。
-
浏览器 { 请求服务端的 j s , c s s ,图片,视频,音频等静态资源 调用浏览器的 h t m l p a r s e r 解析 h t m l 代码 浏览器 \begin{cases}请求服务端的js,css,图片,视频,音频等静态资源 \\\\调用浏 览器的html parser解析html代码 \end{cases} 浏览器⎩ ⎨ ⎧请求服务端的js,css,图片,视频,音频等静态资源调用浏览器的htmlparser解析html代码
-
返回js之后,就会调用js引擎(例如:V8)对js代码解释执行。
-
返回css之后,
就会调用css parser对css解析执行
。??? -
html parser和css parser是两单独的线程,谁先执行完,就等着后一个执行,两个都执行完后,再合成渲染树;再栅格化图层,显示再屏幕上。
-
如果在解析html时,发现js返回,就会阻塞html渲染,先执行完js,在执行html。???
4、哪些操作会阻塞浏览器渲染:
a)、关于css阻塞
在head中使用link引入的外部css,会阻塞dom渲染和js解释执行。
异步加载、异步解析,都阻碍render tree的生成。
CSS | 描述 |
---|---|
style标签中的样式 | (1). 由html解析器进行解析。 (2). 不阻塞浏览器渲染(可能会产生“闪屏现象”)。 (3). 不阻塞DOM解析。 (4). 他是异步解析的,边解析HTML, 边解析style。随即就生成渲染树渲染页面,所以会出现闪屏。 |
link引入的外部css样式 | (1). 由CSS解析器进行解析。当浏览器请求文件后,将同步解析css,当其和html都解析完后才渲染页面。 (2). 阻塞浏览器渲染(可以利用这种阻塞避免“闪屏现象”)。 (3). 阻塞其后面的js语句的执行。 (4). 不阻塞DOM的解析(绝大多数浏览器的工作方式)。 |
优化核心理念:尽可能快的提高外部css加载速度 | (1). 使用CDN节点进行外部资源加速。 (2). 对css进行压缩(利用打包工具,比如webpack,gulp等)。 (3). 减少http请求数,将多个css文件合并。 (4). 优化样式表的代码。 |
b)、关于js阻塞:
script的加载或者执,都会阻塞dom和cssom渲染。
同步加载,同步解析,完全阻塞html解析和首屏污染
js | 原因 |
---|---|
阻塞后续DOM解析 | 浏览器不知道后续脚本的内容,如果先去解析了下面的DOM,而随后的js删除了后面所有的DOM, 那么浏览器就做了无用功,浏览器无法预估脚本里面具体做了什么操作, 例如像document.write 这种操作,索性全部停住,等脚本执行完了,浏览器再继续向下解析DOM。 |
阻塞页面渲染 | js中也可以给DOM设置样式,浏览器等该脚本执行完毕,渲染出一个最终结果,避免做无用功。 |
阻塞后续js的执行 | 维护依赖关系,例如:必须先引入jQuery再引入bootstrap。 |
c)、小结:
- css的解析和js的执行是互斥的(互相排斥),css解析的时候js停止执行,js执行的时候css停止解析。
- 无论css阻塞,还是js阻塞,都不会阻塞浏览器加载外部资源(图片、视频、样式、脚本等)原因:浏览器始终处于一种:“先把请求发出去”的工作模式,只要是涉及到网络请求的内容,无论是:图片、样式、脚本,都会先发送请求去获取资源,至于资源到本地之后什么时候用,由浏览器自己协调。这种做法效率很高。
- WebKit 和 Firefox 都进行了【预解析】这项优化。在执行js脚本时,浏览器的其他线程会预解析文档的其余部分,找出并加载需要通过网络加载的其他资源。通过这种方式,资源可以在并行连接上加载从而提高总体速度。请注意,预解析器不会修改 DOM 树。
- 在上述的过程中,网页在加载和渲染过程中会触发“DOMContentLoaded”和“onload”事件 分别是在DOM树构建(解析)完成之后,以及DOM树构建完并且网页所依赖的资源都加载完之后。
5、在head中引入样式和body中引入有什么区别:
- 加载过程是否阻塞
- 加载顺序
6、如何通过工具分析资源的加载,解析,渲染性能:
采用浏览器的performance
7、资源的优先级:
分为5级:最高,高,中等,低,最低。