来源于:http://yangfch3.com/2017/03/04/%E6%B5%8F%E8%A7%88%E5%99%A8%E5%86%85%E6%A0%B8%E3%80%81%E9%A1%B5%E9%9D%A2%E5%91%88%E7%8E%B0%E5%8E%9F%E7%90%86%E5%8F%8A%E5%85%B6%E4%BC%98%E5%8C%96/css
介绍浏览器内核、页面呈现原理等基础知识,同时根据原理提出页面呈现优化方案。html
浏览器内核又叫渲染引擎,主要负责 HTML、CSS 的解析,页面布局、渲染与复合层合成。浏览器内核的不一样带来的主要问题是对 CSS 的支持度与属性表现差别。git
如今主流的内核有:Blink、Webkit、Gecko、EdgeHTML、Trident,这里面有几个须要注意的地方:github
Blink 是在 Webkit 的基础上的改进,是如今对新特性支持度最好的内核web
移动端基本上所有是 Webkit 或 Blink 内核(除去 Android 上腾讯家的 X5),这两个内核对新特性的支持度较高,因此新特性能够在移动端大展身手。chrome
Trident 是 IE4+ 的内核,一直持续到 IE11,EdgeHTML 是微软抛弃 IE 后开发的全新内核canvas
更多资料请看附录表格segmentfault
通常现代浏览器都会有如下几种渲染模式:浏览器
在 IE5 与 NS4 那个年代,浏览器大战,标准未立,Web 则在经历早期快速地发展。缓存
后来标准逐步创建,新标准的规范与之前 IE五、NS4 的实现存在着不可避免的差别差别,可是此时的网络世界许许多多旧时的页面正在运行,若是按照新标准的实现来渲染的话会有大量的问题出现。
因此此时大部分现代浏览器厂商想到了区别性地使用不一样渲染模式来对待这些 Web 页面。
而 IE 随着升级,对现代标准的支持也愈来愈完善,因此 IE 为了正常渲染旧时页面,支持咱们指定哪一个版本的 IE 模式来渲染页面。
总结就是:
标准未立以前,HTML 文档是没有文档头的,同时在 HTML5 以前的 HTML4/3 的文档头都有各自的特征,因此在大部分现代浏览器下触发的机制以下:
无 DOCTYPE
头触发怪异模式
DOCTYPE
头不正确(不是 html)也触发怪异模式
如:
<!DOCTYPE svg>
DOCTYPE
头为 HTML3 头触发怪异模式
DOCTYPE
头为 HTML4 头则触发接近标准模式(或称有限怪异模式)
常见的 HTML5 DOCTYPE 声明则使用标准模式
在 IE 下,除了文档头的差别能够自动触发渲染模式的选择,咱们还能手动指定(在 IE8+ 适用)使用哪一个版本的 IE 渲染模式来渲染咱们的页面(扩展阅读):
1 2 3 4 5 6 7 8 9 |
<!-- 使用当前操做系统已装的最新的 IE --> <!-- chrome=1 是针对双核浏览器使优先使用 Chrome --> <meta http-equiv="x-ua-compatible" content="ie=edge,chrome=1">
<!-- 使用 IE9 --> <meta http-equiv="x-ua-compatible" content="ie=9">
<!-- 若是你须要使用 IE5 的怪异模式 --> <meta http-equiv="x-ua-compatible" content="ie=5"> |
怪异模式与标准模式
- 怪异模式使用不一样于标准的盒模型(也就至关于 IE8+ 下的:
box-sizing: border-box
)- 怪异模式下某些行内(inline)元素的垂直对齐行为表现怪异:怪异模式下对齐图片至包含它们的盒子的下边框,而 标准模式图片对其到父盒的 baseline
接近标准模式(有限怪异模式)与标准模式
主要区别即为上面的第 2 点
JavaScript 负责 JavaScript 代码的解释与执行,主流的 JavaScript 引擎有:V八、SpiderMonkey、JavaScriptCore、Chakra。
浏览器与引擎详情见附录表格。
当咱们点击一个连接,服务器将 HTML 代码传输到咱们的浏览器,浏览器在接收到这份 HTML 代码以后是如何一步步将页面呈现出来的呢?这里面浏览器须要作哪些工做?如何优化呈现的过程提高 Web 应用质量?
一个页面的呈现,粗略的说会通过如下这些步骤:
DOM 树的构建(Parse HTML)
构建 CSSOM 树(Recaculate Style)
为何是 Re-caculate Style 呢?这是由于浏览器自己有
User Agent StyleSheet
,因此最终的样式是咱们的样式代码样式与用户代理默认样式覆盖/从新计算获得的。
合并 DOM 树与 CSSOM 树为 Render 树
布局(Layout)
绘制(Paint)
复合图层化(Composite)
图层化是本身理解后形象的意译
其中布局(Layout)环节主要负责各元素尺寸、位置的计算,绘制(Paint)环节则是绘制页面像素信息,合成(Composite)环节是多个复合层的合成,最终合成的页面被用户看到。
虽然六部曲看似和谐,分工合做,有序进行。可是实际上这里面倒是波云诡谲,风起云涌,就像平时的工做同样,看似你和我各司其职,分工明确,可是实际干起活来却可能由于某一我的的某一环而阻滞整个进度。
咱们来分析这六部曲中存在的阻塞问题:
当遇到 JavaScript 脚本或者外部 JavaScript 代码时,浏览器便中止 DOM 的构建(阻塞 1)
那是否停下 DOM 的构建的同时,立马就执行 JavaScript 代码或者下载外部脚本执行,其实仍是要视状况而定,见 2
当遇到 <script>
标签须要执行脚本代码时,浏览器会检查是否这个 <script>
标签以上的 CSS 文件是否已经加载并用于构建了 CSSOM,若是 <script>
上部还有 CSS 样式没加载,则浏览器会等待 <script>
上方样式的加载完成才会执行该 <script>
内的脚本(阻塞 2)
DOM 树与 CSSOM 树的成功构建是后面步骤的根基(同步阻塞)
同时外部脚本、外部样式表的下载也是耗费时间较多的点
浏览器构建 DOM 树能够简单的总结为如下几步:
转码(Bytes -> Characters)—— 读取接收到的 HTML 二进制数据,按指定编码格式将字节转换为 HTML 字符串
Tokens 化(Characters -> Tokens)—— 解析 HTML,将 HTML 字符串转换为结构清晰的 Tokens,每一个 Token 都有特殊的含义同时有本身的一套规则
构建 Nodes(Tokens -> Nodes)—— 每一个 Node 都添加特定的属性(或属性访问器),经过指针可以肯定 Node 的父、子、兄弟关系和所属 treeScope(例如:iframe 的 treeScope 与外层页面的 treeScope 不一样)
构建 DOM 树(Nodes -> DOM Tree)—— 最重要的工做是创建起每一个结点的父子兄弟关系
在 Chrome 开发者工具下 Timeline 面板的
Parse HTML
阶段对应着 DOM 树的构建。
CSSOM 树的构建 “原料” 的来源有:外部 CSS 文件、内部样式、内联样式。
CSSOM 树的构建实际上是一个 样式的从新计算 的过程,为何是从新计算呢?
用户代理(即浏览器)自己有一套内置样式表,因此咱们最终的 CSSOM 树实际上是用户代理样式与页面全部样式的从新计算。
因此在 Chrome 浏览器开发者工具的 Timeline 面板下,CSSOM 树的构建对应的是
Recalculate Style
阶段
与 DOM 树的构建过程类似,CSSOM 的构建也要经历如下过程:
最终构建的 CSSOM 树大体以下:
DOM 树与 CSSOM 树融合成渲染树
渲染树只包括渲染页面须要的节点
排除
<script>
<meta>
等功能化、非视觉节点
排除display: none
的节点
Layout 阶段作的工做:肯定页面各元素的位置、尺寸。
Layout 在 Chrome 开发者工具 Timeline 面板中被归并到 Paint 阶段
当元素某些样式变动/JavaScript 执行某些样式请求,会致使 Layout trashing
,又叫作回流(Reflow)。
一旦布局(Layout)步骤完成,浏览器便触发 “Paint Setup” 与 “Paint” 事件(渲染引擎底层概念),执行 paint
操做,结合渲染树与布局信息绘制实际像素。
注:在 Timeline 工具内,
Layout
与Paint
两个过程被统一归并到Paint
阶段。
在不少状况下,咱们不会将复合图层化纳入页面呈现的必要过程。图层化是浏览器为了充分利用已有渲染成果(缓存渲染成果),最小化 GPU 运算,将“脏区”提高为复合图层,隔离变化影响的操做。
见 连接
知道了页面渲染的原理,那么咱们也就获得了页面性能优化的依据。提炼六部曲中每一步的优化空间,针对六部曲中的每一步提出针对性的优化方案也就能达到咱们最终的优化目的。
关键呈现路径里的一些概念:
优化关键呈现路径的指导原则:
优化关键呈现路径常规步骤:
优化关键呈现路径的具体建议:
文件合并、压缩
推荐使用异步(async
) JavaScript 资源,或使用延迟(defer
)执行的 JavaScript
通常 <script>
脚本的靠后书写
避免运行时间长的 JavaScript,耗时任务的拆分,chunk 化运行
例如:使用定时器将大任务拆分为小任务,使得浏览器获得空隙作其余事情。
避免使用 CSS import
内联、内部化阻止呈现的 CSS
通常不采用,百度、Google 这样的极度重视性能与体验的服务才可能这样作。
由于浏览器有图层化这个机制,那么咱们就搞懂它并充分利用吧。
某些属性的变动(transform
、opacity
)知足如下条件:
那么这些属性变动时就须要一种机制:机制须要能将属性变动的部分与页面其余部分隔离开来,其余部分已经渲染无缺进行缓存,变动的部分在单独的图层上进行,而后对缓存的部分与变动的图层进行合成。
因此图层化的关键字:缓存、隔离、图层合成
使用 transform
与 opacity
进行属性变动是经典的符合图层化方法,如下是其余会提高元素为复合图层的场景:
translate3d
, translateZ
等等(JS 通常经过这种方式,使元素得到复合图层)<video>
<iframe>
<canvas>
<webgl>
等元素。opacity
和 transform
作 CSS 动画。will-change
属性。position:fixed
。z-index
较低且包含一个复合层的兄弟元素(换句话说就是该元素在复合层上方)很容易看出来:充分利用缓存、隔离的思想,无需像回流、重绘那么大性能(GPU、CPU)开支,图层化能带来动画性能的提高。
那么图层化的弊端在哪里呢?
由于图层化的存在,每一个图层对须要在内存中存储该图层相关的信息,当图层太多会形成内存开销过大的状况(以下图)。
![image_1baah8s0vcol3464t21foe1sb91g.png-31.3kB][7]
一样表现的页面,单图层与多图层的内存开销
内存开销在桌面端可能还能接受,可是在资源有限的移动端,复合图层过多即可能致使内存开支过大,页面反而变得停滞、卡顿,甚至浏览器假死,系统没法正常运行。
transfrom
, opacity
background-color
等position
- top
bottom
left
right
width
height
等margin
, padding
, border
JavaScript 存在这样的机制:当连续有大量 DOM 样式的操做时,出于性能考虑,防止零碎变动致使频繁的回流、重绘,会尽量地将这些操做先缓存起来,而后一次性地变动。这个机制咱们难以察觉可是确实存在。
然而当咱们进行某些 DOM 样式的读、写时,出于时效性的考虑,则会当即触发浏览器回流、重绘以返回正确、合理的值。
已经比较明白了,那就略吧
也已经比较明白,也略吧
使用 Timeline 工具咱们能作如下事:
理解 Timeline 工具使用,读懂这图就够了
经常使用事件,更多事件见[扩展阅读](#扩展阅读)
而咱们在平常开发中,用 Timeline 最多的场景是:
选择性地开启如下开关
开启开发者工具实验性特性开关
Timeline 官方简介
Timeline 事件参考
推荐:Timeline 进行帧分析,避免页面卡顿
浏览器/RunTime | 内核(渲染引擎) | JavaScript 引擎 |
---|---|---|
Chrome | Blink(28~) Webkit(Chrome 27) |
V8 |
FireFox | Gecko | SpiderMonkey |
Safari | Webkit | JavaScriptCore |
Edge | EdgeHTML | Chakra(for JavaScript) |
IE | Trident | Chakra(for JScript) |
PhantomJS | Webkit | JavaScriptCore |
Node.js | - | V8 |