菜单

无线性能优化:Composite

2018年11月15日 - CSS/CSS3

无线性能优化:Composite

2016/04/26 · 基本功技术 ·
无线

初稿出处: 淘宝前端团队(FED)-
冬萌   

图片 1

一个 Web 页面的显示,简单的话可看更了以下下几乎独步骤。

图片 2

理所当然,本文我们只是来关怀 Composite 部分。

初稿出处: 淘宝前端团队(FED)-
妙净   

浏览器渲染原理

每当讨论 Composite 之前,有必要先简单了解下一些浏览器(本文特是本着 Chrome
来说)的渲染原理,方便对后有概念的明。更多详细的情可以参阅 GPU
Accelerated Compositing in
Chrome

流动:由于 Chrome 对 Blank
引擎某些实现之修改,某些我们事先熟知的类名有了转,比如 RenderObject
变成了 LayoutObject,RenderLayer 变成了 PaintLayer。感兴趣的羁押因为参阅
Slimming Paint。

以浏览器被,页面内容是储存为由 Node 对象成的树状结构,也就算是 DOM
树。每一个 HTML element 元素都出一个 Node 对象与之相应,DOM
树的彻底节点永远都是 Document Node。这或多或少信任大家都颇熟稔了,但实在,从
DOM 树到终极之渲染,需要展开一些易映射。

图片 3

图片 4

从 Nodes 到 LayoutObjects

DOM 树中得每个 Node 节点都有一个对应的 LayoutObject 。LayoutObject
知道什么样在屏幕及 paint Node 的内容。

如何吃页面尽可能早地渲染页面,页面重新早可见,让白屏时间再缺少,尤其是无线环境下,一直是性优化的话题。

从 LayoutObjects 到 PaintLayers

诚如的话,拥有同等之坐标空间的
LayoutObjects,属于同一个渲染层(PaintLayer)。PaintLayer 最初是故来兑现
stacking
contest(层叠上下文),以这个来保证页面元素以对的依次合成(composite),这样才会对的展示元素的交汇和半透明元素等等。因此满足形成层叠上下文条件的
LayoutObject
一定会呢其创建新的渲染层,当然还发另外的组成部分非正规情况,为一些非正规的
LayoutObjects 创建一个新的渲染层,比如 overflow != visible
的元素。根据创造 PaintLayer 的来由莫衷一是,可以将该分成大的 3 类:

满足上述条件的 LayoutObject 会拥有独立的渲染层,而其他的 LayoutObject
则与那个首先个有渲染层的父元素共用一个。

页面可见时间

页面可见要更以下过程:

图片 5

layout

图片 6

由 JS 可能天天会改 DOMCSSOM,当页面被生出雅量的 JS
想这实施时,浏览器下载并尽,直到完成 CSSOM
下充斥及构建,而当我们等时,DOM 构建同样深受死。为了 JS 不阻塞 DOM 和
CSSDOM 的构建,不影响首屏可见的时,测试几种 JS
加载策略对页面可见的震慑:

从 PaintLayers 到 GraphicsLayers

或多或少特殊的渲染层会吃当是合成层(Compositing Layers),合成层拥有独立的
GraphicsLayer,而其他不是合成层的渲染层,则跟夫首先单有 GraphicsLayer
父层公用一个。

每个 GraphicsLayer 都发出一个 GraphicsContext,GraphicsContext
会负责输出该层的位图,位图是储存在共享内存中,作为纹理上传到 GPU
中,最后由于 GPU 将多独各类图进行合成,然后 draw
到屏幕上,此时,我们的页面也便见到了屏幕及。

渲染层提升也合成层的因产生瞬间几乎栽:

注:渲染层提升为合成层有一个先决条件,该渲染层必须是
SelfPaintingLayer(基本不过认为是上文介绍的
NormalPaintLayer)。以下所谈论的渲染层提升为合成层的情都是以拖欠渲染层为
SelfPaintingLayer 前提下之。

几栽异步加载方式测试

JavaScript

function injectWrite(src){ document.write('<script src="' + src +
'"></sc' + 'ript>'); }

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5a721bbc827ff070447677-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5a721bbc827ff070447677-2">
2
</div>
<div class="crayon-num" data-line="crayon-5a721bbc827ff070447677-3">
3
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5a721bbc827ff070447677-1" class="crayon-line">
function injectWrite(src){
</div>
<div id="crayon-5a721bbc827ff070447677-2" class="crayon-line crayon-striped-line">
  document.write('&lt;script src=&quot;' + src + '&quot;&gt;&lt;/sc' + 'ript&gt;');
</div>
<div id="crayon-5a721bbc827ff070447677-3" class="crayon-line">
}
</div>
</div></td>
</tr>
</tbody>
</table>
JavaScript

&lt;script&gt; var script = document.createElement('script');
script.src = "//g.tbcdn.com/xx.js";
document.getElementsByTagName('head')\[0\].appendChild(script);
&lt;/script&gt;

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5a721bbc82807359027480-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5a721bbc82807359027480-2">
2
</div>
<div class="crayon-num" data-line="crayon-5a721bbc82807359027480-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5a721bbc82807359027480-4">
4
</div>
<div class="crayon-num" data-line="crayon-5a721bbc82807359027480-5">
5
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5a721bbc82807359027480-1" class="crayon-line">
&lt;script&gt;
</div>
<div id="crayon-5a721bbc82807359027480-2" class="crayon-line crayon-striped-line">
  var script = document.createElement('script');
</div>
<div id="crayon-5a721bbc82807359027480-3" class="crayon-line">
  script.src = &quot;//g.tbcdn.com/xx.js&quot;;
</div>
<div id="crayon-5a721bbc82807359027480-4" class="crayon-line crayon-striped-line">
  document.getElementsByTagName('head')[0].appendChild(script);
</div>
<div id="crayon-5a721bbc82807359027480-5" class="crayon-line">
&lt;/script&gt;
</div>
</div></td>
</tr>
</tbody>
</table>

层压缩

大抵周边的部分合成层的升官原因一旦达到所说,你晤面发现,由于重叠的原因,可能无限制就会生出大量合成层来,而每个合成层都如耗费
CPU
和内存资源,岂不是惨重影响页面性能。这一点浏览器为设想到了,因此即使有矣层压缩(Layer
Squashing)的拍卖。如果多只渲染层同一个合成层重叠时,这些渲染层会给缩减到一个
GraphicsLayer
中,以戒出于重叠原因造成可能出现的“层爆炸”。具体可看如下
demo。一开始,蓝色方块由于
translateZ
提升以合成层,其他的方元素以重叠的因,被缩减了齐,大小就含这
3 个方块的矩形大小。

图片 11

当我们 hover 绿色方块时,会叫其设置 translateZ
属性,导致绿色方块也被升级也合成层,则剩下的少独为削减到了一同,大小就缩小为带有这
2 单方块的矩形大小。

图片 12

自然,浏览器的活动的重叠压缩为不是全能的,有广大一定情景下,浏览器是无能为力展开层压缩的,如下所示,而这些情况也是我们应当尽量避免的。(注:以下情形都是依据重叠原因而言)

CSS

\#ancestor { -webkit-mask-image:
-webkit-linear-gradient(rgba(0,0,0,1), rgba(0,0,0,0)); }
\#composited { width: 100%; height: 100%; transform: translateZ(0);
} \#container { position: relative; width: 400px; height: 60px;
border: 1px solid black; } \#overlap-child { position: absolute;
left: 0; top: 0 ; bottom: 0px; width: 100%; height: 60px;
background-color: orange; }

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-4">
4
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-5">
5
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-6">
6
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-7">
7
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-8">
8
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-9">
9
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-10">
10
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-11">
11
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-12">
12
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-13">
13
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-14">
14
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-15">
15
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-16">
16
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-17">
17
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-18">
18
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-19">
19
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-20">
20
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-21">
21
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-22">
22
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-23">
23
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-24">
24
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201886f149137440-25">
25
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201886f149137440-26">
26
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f6d201886f149137440-1" class="crayon-line">
  #ancestor {
</div>
<div id="crayon-5b8f6d201886f149137440-2" class="crayon-line crayon-striped-line">
    -webkit-mask-image: -webkit-linear-gradient(rgba(0,0,0,1), rgba(0,0,0,0));
</div>
<div id="crayon-5b8f6d201886f149137440-3" class="crayon-line">
  }
</div>
<div id="crayon-5b8f6d201886f149137440-4" class="crayon-line crayon-striped-line">
  
</div>
<div id="crayon-5b8f6d201886f149137440-5" class="crayon-line">
  #composited {
</div>
<div id="crayon-5b8f6d201886f149137440-6" class="crayon-line crayon-striped-line">
    width: 100%;
</div>
<div id="crayon-5b8f6d201886f149137440-7" class="crayon-line">
    height: 100%;
</div>
<div id="crayon-5b8f6d201886f149137440-8" class="crayon-line crayon-striped-line">
    transform: translateZ(0);
</div>
<div id="crayon-5b8f6d201886f149137440-9" class="crayon-line">
  }
</div>
<div id="crayon-5b8f6d201886f149137440-10" class="crayon-line crayon-striped-line">
 
</div>
<div id="crayon-5b8f6d201886f149137440-11" class="crayon-line">
  #container {
</div>
<div id="crayon-5b8f6d201886f149137440-12" class="crayon-line crayon-striped-line">
    position: relative;
</div>
<div id="crayon-5b8f6d201886f149137440-13" class="crayon-line">
    width: 400px;
</div>
<div id="crayon-5b8f6d201886f149137440-14" class="crayon-line crayon-striped-line">
    height: 60px;
</div>
<div id="crayon-5b8f6d201886f149137440-15" class="crayon-line">
    border: 1px solid black;
</div>
<div id="crayon-5b8f6d201886f149137440-16" class="crayon-line crayon-striped-line">
  }
</div>
<div id="crayon-5b8f6d201886f149137440-17" class="crayon-line">
 
</div>
<div id="crayon-5b8f6d201886f149137440-18" class="crayon-line crayon-striped-line">
  #overlap-child {
</div>
<div id="crayon-5b8f6d201886f149137440-19" class="crayon-line">
    position: absolute;
</div>
<div id="crayon-5b8f6d201886f149137440-20" class="crayon-line crayon-striped-line">
    left: 0;
</div>
<div id="crayon-5b8f6d201886f149137440-21" class="crayon-line">
    top: 0 ;
</div>
<div id="crayon-5b8f6d201886f149137440-22" class="crayon-line crayon-striped-line">
    bottom: 0px;
</div>
<div id="crayon-5b8f6d201886f149137440-23" class="crayon-line">
    width: 100%;
</div>
<div id="crayon-5b8f6d201886f149137440-24" class="crayon-line crayon-striped-line">
    height: 60px;
</div>
<div id="crayon-5b8f6d201886f149137440-25" class="crayon-line">
    background-color: orange;
</div>
<div id="crayon-5b8f6d201886f149137440-26" class="crayon-line crayon-striped-line">
  }
</div>
</div></td>
</tr>
</tbody>
</table>




XHTML

&lt;div id="container"&gt; &lt;div id="composited"&gt;Text behind
the orange box.&lt;/div&gt; &lt;div id="ancestor"&gt; &lt;div
id="overlap-child"&gt;&lt;/div&gt; &lt;/div&gt; &lt;/div&gt;

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f6d201887b075031864-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201887b075031864-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201887b075031864-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201887b075031864-4">
4
</div>
<div class="crayon-num" data-line="crayon-5b8f6d201887b075031864-5">
5
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d201887b075031864-6">
6
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f6d201887b075031864-1" class="crayon-line">
&lt;div id=&quot;container&quot;&gt;
</div>
<div id="crayon-5b8f6d201887b075031864-2" class="crayon-line crayon-striped-line">
  &lt;div id=&quot;composited&quot;&gt;Text behind the orange box.&lt;/div&gt;
</div>
<div id="crayon-5b8f6d201887b075031864-3" class="crayon-line">
  &lt;div id=&quot;ancestor&quot;&gt;
</div>
<div id="crayon-5b8f6d201887b075031864-4" class="crayon-line crayon-striped-line">
    &lt;div id=&quot;overlap-child&quot;&gt;&lt;/div&gt;
</div>
<div id="crayon-5b8f6d201887b075031864-5" class="crayon-line">
  &lt;/div&gt;
</div>
<div id="crayon-5b8f6d201887b075031864-6" class="crayon-line crayon-striped-line">
&lt;/div&gt;
</div>
</div></td>
</tr>
</tbody>
</table>

CSS

.clipping-container { overflow: hidden; height: 10px;
background-color: blue; } .composited { transform: translateZ(0);
height: 10px; background-color: red; } .target { position:absolute;
top: 0px; height:100px; width:100px; background-color: green; color:
\#fff; }

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018880297868155-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018880297868155-4">
4
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-5">
5
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018880297868155-6">
6
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-7">
7
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018880297868155-8">
8
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-9">
9
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018880297868155-10">
10
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-11">
11
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018880297868155-12">
12
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-13">
13
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018880297868155-14">
14
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-15">
15
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018880297868155-16">
16
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-17">
17
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018880297868155-18">
18
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-19">
19
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018880297868155-20">
20
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-21">
21
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018880297868155-22">
22
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018880297868155-23">
23
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f6d2018880297868155-1" class="crayon-line">
.clipping-container {
</div>
<div id="crayon-5b8f6d2018880297868155-2" class="crayon-line crayon-striped-line">
 
</div>
<div id="crayon-5b8f6d2018880297868155-3" class="crayon-line">
    overflow: hidden;
</div>
<div id="crayon-5b8f6d2018880297868155-4" class="crayon-line crayon-striped-line">
    height: 10px; 
</div>
<div id="crayon-5b8f6d2018880297868155-5" class="crayon-line">
    background-color: blue;
</div>
<div id="crayon-5b8f6d2018880297868155-6" class="crayon-line crayon-striped-line">
  }
</div>
<div id="crayon-5b8f6d2018880297868155-7" class="crayon-line">
 
</div>
<div id="crayon-5b8f6d2018880297868155-8" class="crayon-line crayon-striped-line">
  .composited {
</div>
<div id="crayon-5b8f6d2018880297868155-9" class="crayon-line">
 
</div>
<div id="crayon-5b8f6d2018880297868155-10" class="crayon-line crayon-striped-line">
    transform: translateZ(0); 
</div>
<div id="crayon-5b8f6d2018880297868155-11" class="crayon-line">
    height: 10px; 
</div>
<div id="crayon-5b8f6d2018880297868155-12" class="crayon-line crayon-striped-line">
    background-color: red;
</div>
<div id="crayon-5b8f6d2018880297868155-13" class="crayon-line">
  }
</div>
<div id="crayon-5b8f6d2018880297868155-14" class="crayon-line crayon-striped-line">
 
</div>
<div id="crayon-5b8f6d2018880297868155-15" class="crayon-line">
  .target {
</div>
<div id="crayon-5b8f6d2018880297868155-16" class="crayon-line crayon-striped-line">
 
</div>
<div id="crayon-5b8f6d2018880297868155-17" class="crayon-line">
    position:absolute; 
</div>
<div id="crayon-5b8f6d2018880297868155-18" class="crayon-line crayon-striped-line">
    top: 0px; 
</div>
<div id="crayon-5b8f6d2018880297868155-19" class="crayon-line">
    height:100px; 
</div>
<div id="crayon-5b8f6d2018880297868155-20" class="crayon-line crayon-striped-line">
    width:100px; 
</div>
<div id="crayon-5b8f6d2018880297868155-21" class="crayon-line">
    background-color: green;
</div>
<div id="crayon-5b8f6d2018880297868155-22" class="crayon-line crayon-striped-line">
    color: #fff;
</div>
<div id="crayon-5b8f6d2018880297868155-23" class="crayon-line">
  }
</div>
</div></td>
</tr>
</tbody>
</table>




XHTML

&lt;div class="clipping-container"&gt; &lt;div
class="composited"&gt;&lt;/div&gt; &lt;/div&gt; &lt;div
class="target"&gt;不会被压缩到 composited div 上&lt;/div&gt;

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f6d2018884301689224-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018884301689224-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f6d2018884301689224-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6d2018884301689224-4">
4
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f6d2018884301689224-1" class="crayon-line">
&lt;div class=&quot;clipping-container&quot;&gt;
</div>
<div id="crayon-5b8f6d2018884301689224-2" class="crayon-line crayon-striped-line">
  &lt;div class=&quot;composited&quot;&gt;&lt;/div&gt;
</div>
<div id="crayon-5b8f6d2018884301689224-3" class="crayon-line">
&lt;/div&gt;
</div>
<div id="crayon-5b8f6d2018884301689224-4" class="crayon-line crayon-striped-line">
&lt;div class=&quot;target&quot;&gt;不会被压缩到 composited div 上&lt;/div&gt;
</div>
</div></td>
</tr>
</tbody>
</table>


本例中 .target 同 合成层 `.composited` 重叠,但是由于
.composited`在一个 overflow: hidden 的容器中,导致 .target 和合成层有不同的裁剪容器,从而 `.target` 无法被压缩。`

CSS

body { height: 1500px; overflow-x: hidden; } .composited { width: 50px;
height: 50px; background-color: red; position: absolute; left: 50px;
top: 400px; transform: translateZ(0); } .overlap { width: 200px; height:
200px; background-color: green; position: fixed; left: 0px; top: 0px; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
body {
    height: 1500px;
    overflow-x: hidden;
  }
 
  .composited {
 
    width: 50px;
    height: 50px;
    background-color: red;
    position: absolute;
    left: 50px;
    top: 400px;
    transform: translateZ(0);
  }
 
  .overlap {
    width: 200px;
    height: 200px;
    background-color: green;
    position: fixed;
    left: 0px;
    top: 0px;
  }

XHTML

<div class=”composited”></div> <div
class=”overlap”></div>

1
2
<div class="composited"></div>
<div class="overlap"></div>

本例中,红色的
.composited提升为了合成层,绿色的.overlapfix 在页面顶部,一开始只有.composited合成层。

![](https://img.alicdn.com/tps/TB1SHBOMXXXXXbnXFXXXXXXXXXX-690-484.jpg\_640x640.jpg)

当滑动页面,.overlap重叠到.composited上时,.overlap`
会因重叠原因提升也合成层,同时,因为相对于合成层滚动,因此无法让减去。

![](https://img.alicdn.com/tps/TB1IrRGMXXXXXXxaXXXXXXXXXXX-690-484.jpg\_640x640.jpg)

测试结果

以下提到的 domReadyDOMContentLoaded 事件。

A (head script) B (bottom script) C (document.write) D (getScript) E (async) F (defer) G (async + defer)
1 PC Chrome 页面白屏长、domReady:5902.545、onLoad:5931.48 页面先显示、domReady:5805.21、onLoad:5838.255 页面先显示、domReady:5917.95、onLoad:5949.30 页面先显示、domReady:244.41、onLoad:5857.645 页面先显示、domReady:567.01、onLoad:5709.33 页面先显示、domReady:5812.12、onLoad:5845.6 页面先显示、domReady:576.12、onLoad:5743.79
2 iOS Safari 页面白屏长、domReady:6130、onLoad:6268.41 页面白屏长、domReady:5175.80、onLoad:5182.75 页面白屏长、domReady:5617.645、onLoad:5622.115 502s 白屏然后页面显示最后变更 load finish 时间、domReady:502.71、onLoad:6032.95 508s 白屏然后页面显示最后变更 load finish time domReady:508.95、onLoad:5538.135 页面白屏长、domReady:5178.98、onLoad:5193.58 556s 白屏然后页面显示最后变更 load finish 时间、domReady:556、onLoad:5171.95
3 iOS 手淘 WebView 页面白屏长、页面出现 loading 消失、domReady: 5291.29、onLoad:5292.78 页面白屏长、页面未跳转 loading 消失、domReady: 5123.46、onLoad:5127.85 页面白屏长、页面未跳转 loading 消失、domReady: 5074.86、onLoad:5079.875 页面可见快、loading 消失快在 domReady 稍后、domReady:14.06、load finish:5141.735 页面可见快、loading 消失快在 domReady 稍后、domReady:13.89、load finish:5157.15 页面白屏长、loading 先消失再出现页面、domReady: 5132.395、onLoad:5137.52 页面可见快、然后 loading 消失、domReady:13.49、load finish:5124.08
4 Android browser 页面白屏长、domReady: 5097.29、onLoad:5100.37 页面白屏长、domReady: 5177.48、onLoad:5193.66 页面白屏长、domReady: 5125.96、onLoad:5165.06 页面可见快、等 5s 后更新 load finish 时间 domReady:463.33、load finish:5092.90 页面可见快、等 5s 后更新 load finish 时间 domReady:39.34、load finish:5136.55 页面白屏长、domReady: 5092.45、onLoad:5119.81 页面可见快、等 5s 后更新 load finish 时间 domReady:50.49、load finish:5507.668
5 Android 手淘 WebView 白屏时间长、一直 loading 直接页面可见、domReady:5058.91、onLoad:5073.81 页面立即可见、loading 消失快、等 5s 后更新 domReady 时间和 load 时间 domReady:4176.34、onLoad:4209.50 页面立即可见、loading 消失快、domReady:6011.18、onLoad:6031.93 页面可见快、loading 之后消失、等 5s 后更新 load finish 时间 domReady:36.31、load finish:5081.76 页面可见快、loading 随后消失、等 5s 后更新 load finish 时间 domReady:25.11、load finish:5113.81 页面可见快、loading 随后消失、等 5s 后更新 domReady 时间和 load 时间 domReady:5213.11、load finish:5312.19 页面可见快、loading 随后消失、等 5s 后更新 load finish 时间 domReady:89.67、load finish:5589.95

自以上测试结果好看来以下结论:

怎么样查看合成层

采用 Chrome DevTools 工具来查阅页面被合成层的景。

比较简单的方式是打开 DevTools,勾选上 Show layer borders

图片 14

其中,页面及之合成层会就此黄色边框框出来。

图片 15

自然,更加详实的信息可以由此 Timeline 来查看。

每一个独门的轴,看到每个帧的渲染细节:

图片 16

点击后,你就算会当视图中观看一个初的挑三拣四项卡:Layers。

图片 17

点击是 Layers
选项卡,你晤面看出一个初的视图。在是视图中,你可针对当时等同幅中之备合成层进行围观、缩放等操作,同时还会望每个渲染层被创造的由。

图片 18

来矣这视图,你就算能够了解页面被究竟有微微个合成层。如果您于针对页面滚动或逐渐变效果的习性分析着发现
Composite
过程耗费了不过多日子,那么您可以打之视图里看到页面被生小个渲染层,它们为何让创造,从而对合成层的数额进行优化。

didFinishLoad 到底什么时候接触

didFinishLoad 是 native 定义之风波,该事件触发时手淘 loading
菊花消失,并且 windvane 中的发出请求不再收集,也就是是 native 统计有底
pageLoad 时间。在用户数据平台来看底瀑布流请求,就是当 didFinishLoad
触发前收集及之享有请求。

图片 19

透过头测试,客户端的 didFinisheLoad 事件的触及和 JS 中之
domReady(DOMContentLoaded)和 onLoad 触发没有外关联。可能在 domReady
之前要之后,也恐怕当 onLoad 之前还是后。

那它们到底是呀时候接触呢? iOS
官方文档
是 Sent after a web view finishes loading a frame。
结合收集的用户请求与测试,didFinishLoad
是于接连发起的要了后触发,监听一段时间内无求虽触发。

就此时会面相 data_sufei 这个 JS
文件,在多少用户之瀑布流里面有,在稍用户的又尚未。原因是以此 JS 是
aplus_wap.js 故意 setTimeout 1s 后发生的,如果页面在 1s
前怀有的乞求都发了了虽然触发 didFinishLoad,后面的 data_sufei.js
的岁月即非算是到 pageLoad 的日;反的要类似 1s
页面还有图片等要还以作,则 data_sufei.js 的时空啊会叫算到里头。

从而当 JS 中之所以 setTimeout 来推迟发送请求也时有发生或会见潜移默化 didFinishLoad
的日子,建议 setTimeout 的光阴设置得重增长一些,如 3s。

性优化

晋升为合成层简单说来有以下几点好处:

使用合成层对于升级页面性能方面发出死要命的意,因此我们呢总了一晃几乎沾优化建议。

async 和 defer

script 标签及得增长 defer 和 async 属性来优化是 script 的下载和执行。

升级动画效果的元素

合成层的利是勿会见潜移默化及任何因素的绘图,因此,为了减少动画元素对另因素的熏陶,从而减少
paint,我们要拿动画效果被的元素提升为合成层。

提升合成层的最好好措施是应用 CSS 的 will-change
属性。从上亦然省合成层产生原因被,可以了解 will-change 设置为
opacity、transform、top、left、bottom、right 可以用元素提升为合成层。

CSS

#target { will-change: transform; }

1
2
3
#target {
  will-change: transform;
}

该匹配如下所示:
图片 20

对于那些目前尚免支持 will-change 属性的浏览器,目前常用的凡使一个 3D
transform 属性来强制提升也合成层:

CSS

#target { transform: translateZ(0); }

1
2
3
#target {
  transform: translateZ(0);
}

但是用小心的凡,不要创建太多之渲染层。因为各级创建一个新的渲染层,就表示新的内存分配与重新扑朔迷离的重合的管理。之后我们见面详细讨论。

假定你已经把一个素放到一个初的合成层里,那么可以以 Timeline
来认可这么做是否真正改进了渲染性能。别盲目提升合成层,一定要分析该实际性能表现。

defer :延迟

HTML 4.0 规范,其用意是,告诉浏览器,等到 DOM+CSSOM
渲染完成,再实践指定脚本。

JavaScript

<script defer src=”xx.js”></script>

1
<script defer src="xx.js"></script>
  • 浏览器开始解析 HTML 网页
  • 剖析过程被,发现带有 defer 属性的 script 标签
  • 浏览器继续往生分析 HTML 网页,解析了就渲染到页面上,同时并行下载
    script 标签中之表面脚本
  • 浏览器就解析 HTML 网页,此时更实践下载的剧本,完成后触发
    DOMContentLoaded

下载的本子文件在 DOMContentLoaded
事件触发前履行(即刚刚读取了标签),而且好保证执行各个就是它们以页面及出现的依次。所以
添加 defer 属性后,domReady
的辰并不曾提前,但其可让页面重新快显示出来。

拿放在页面上的 script 加 defer,在 PC Chrome 下该意义一定给 把此
script 放在脚,页面会先出示。 但对 iOS Safari 和 iOS WebView 加 defer
和 script 放脚同都是加上时白屏。

下 transform 或者 opacity 来促成动画效果

章最开始,我们谈话到了页面呈现出所涉之渲染流水线,其实自从性质方面考虑,最地道的渲染流水线是没有布局以及制图环节的,只需要做合成层的联结即可:

图片 21

为了兑现上述作用,就需就利用那些单纯触发 Composite
的特性。目前,只出点儿独属性是满足这个规格的:transforms 和
opacity。更详尽的音方可查看 CSS Triggers。

顾:元素提升也合成层后,transform 和 opacity 才不见面触发
paint,如果非是合成层,则该依然会触发 paint。具体表现如下两独 demo。

好看看不提升 target element 为合成层,transform 和 opacity 依然会触发
paint。

async: 异步

HTML 5
规范,其作用是,使用另外一个过程下载脚本,下载时无会见堵塞渲染,并且下载完成后旋即执行。

JavaScript

<script async src=”yy.js”></script>

1
<script async src="yy.js"></script>
  • 浏览器开始解析 HTML 网页
  • 分析过程被,发现含有 async 属性的 script 标签
  • 浏览器继续朝着生分析 HTML 网页,解析完先显示页面并触发
    DOMContentLoaded,同时并行下载 script 标签中之外部脚本
  • 本子下载完成,浏览器暂停解析 HTML 网页,开始执行下载的台本
  • 本子执行了,浏览器恢复解析 HTML 网页

async 属性可以包脚本下载的还要,浏览器继续渲染。但是 async
无法确保脚本的实行各个。哪个脚本先下充斥了,就先实行好剧本。

减去绘制区域

对于不需要重绘制的区域应尽可能避免绘制,以减少绘制区域,比如一个 fix
在页面顶部的原则性不变换的领航 header,在页面内容有区域 repaint
时,整个屏幕包括 fix 的 header 也会见给重绘,见
demo,结果如下:

图片 24

假设对一贯不变换的区域,我们期望那并无见面为重绘,因此可经事先的不二法门,将那个升级为独立的合成层。

减少绘制区域,需要细分析页面,区分绘制区域,减少重绘区域还是避免重绘。

安抉择 async 和 defer

合理管理合成层

扣押罢上面的稿子,你见面发觉提升合成层会及更好的性能。这看起来挺诱人,但是问题是,创建一个新的合成层并无是免费之,它得消耗额外的内存和保管资源。实际上,在内存资源有限的配备上,合成层带来的性能改善,可能远远赶不达标了多合成层开销让页面性能带来的负面影响。同时,由于每个渲染层的纹理都待上传来
GPU 处理,因此我们尚亟需考虑 CPU 和 GPU 之间的拉动富问题、以及来差不多要命外存供
GPU 处理这些纹理的题材。

对此合成层占用内存的问题,我们简要做了几乎只 demo 进行了印证。

demo
1
和 demo
2
中,会创造 2000 个一律的 div 元素,不同之凡 demo
2
中之要素通过 will-change 都提升为合成层,而少于独 demo
页面的内存消耗也闹好强烈的歧异。

图片 25

script inject 和 async

JavaScript

<!– BAD –> <script
src=”//g.alicdn.com/large.js”></script> <!– GOOD –>
<script> var script = document.createElement(‘script’); script.src
= “//g.alicdn.com/large.js”;
document.getElementsByTagName(‘head’)[0].appendChild(script);
</script>

1
2
3
4
5
6
7
8
9
  <!– BAD –>
<script src="//g.alicdn.com/large.js"></script>
 
<!– GOOD –>
<script>
  var script = document.createElement(‘script’);
  script.src = "//g.alicdn.com/large.js";
  document.getElementsByTagName(‘head’)[0].appendChild(script);
</script>

咱们日常用这种 inject script 的点子来异步加载文件,特别是原先
Sea.jsKISSY 的盛行时,出现大量行使$.use
来加载页面入口文件。这种措施及 async 的一律都能够异步化
JS,不死页面渲染。但着实是无与伦比抢的呢?

一个普遍的页面如下:一个 CSS,两单异步的 JS

JS 使用 script inject
的方式测试结果如下,DEMO:

图片 26

JS 使用 async 的法子测试结果如下,
DEMO:

图片 27

对比结果发现,通过 “ 的法门的 JS 可以跟 CSS 并作下载,这样一切页面 load
时间更换得重新缺乏,JS
更快执行完毕,这样页面的彼此或数量等得重新快更新。为什么吗?因为浏览器有相近
‘preload
scanner’
的法力,在 HTML 解析时即可提前并作去下充斥 JS 文件,如果将 JS
的文本隐藏在 JS 逻辑中,浏览器就不曾这么智能发现了。

或者大家照面说,现在 CSS/JS
都预加载到客户端了,怎么加载不重要。但页面有或分享下呢生或运行在浏览器被,也起或预加载失效。

综合上面 async 和 defer,推荐以下用法。

JavaScript

<!– 现代浏览器用 ‘async’, ie9-用 ‘defer’ –> <script
src=”//g.alicdn.com/alilog/mlog/aplus_wap.js” async
defer></script>

1
2
<!– 现代浏览器用 ‘async’, ie9-用 ‘defer’ –>
<script src="//g.alicdn.com/alilog/mlog/aplus_wap.js" async defer></script>

实则现在无线站点 aplus.js 可以完全用这种措施引入,既未会见卡住 DOM
CSSOM,也不见面延长整个页面 onLoad 时间,而非是本来的 PC 上的
script inject方式。

假定 aplus.js 在 PC 上这样用,IE 8/IE 9 应用的凡 defer
属性,不会见卡住页面渲染,但是是 JS 需要执行完毕晚才触发
domReady(DOMContentLoaded)事件,故在 IE 8/IE 9 下可能会见潜移默化 domReady
的时间。

预防层爆炸

通过事先的牵线,我们理解和合成层重叠也会见要元素提升也合成层,虽然来浏览器的交汇压缩编制,但是呢发生不少无法进展削减的景。也就是说除了我们显式的声明的合成层,还可能由重叠原因无经过意间产生部分勿在预料的合成层,极端一点或许会见有大量的额外合成层,出现重叠爆炸的场面。我们大概写了一个极点而其实以咱们的页面中较大的
demo。

CSS

@-webkit-keyframes slide { from { transform: none; } to { transform:
translateX(100px); } } .animating { width: 300px; height: 30px;
background-color: orange; color: #fff; -webkit-animation: slide 5s
alternate linear infinite; } ul { padding: 5px; border: 1px solid #000;
} .box { width: 600px; height: 30px; margin-bottom: 5px;
background-color: blue; color: #fff; position: relative; /*
会导致力不从心回落:squashingClippingContainerMismatch */ overflow: hidden;
} .inner { position: absolute; top: 2px; left: 2px; font-size: 16px;
line-height: 16px; padding: 2px; margin: 0; background-color: green; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@-webkit-keyframes slide {
    from { transform: none; }
    to { transform: translateX(100px); }
    }
    .animating {
    
    width: 300px;
    height: 30px;
    background-color: orange;
    color: #fff;
      -webkit-animation: slide 5s alternate linear infinite;
    }
 
  ul {
 
    padding: 5px;
    border: 1px solid #000;
  }
 
    .box {
 
    width: 600px;
    height: 30px;
    margin-bottom: 5px;
    background-color: blue;
    color: #fff;
    position: relative;
    /* 会导致无法压缩:squashingClippingContainerMismatch */
    overflow: hidden;
    }
 
    .inner {
      position: absolute;
      top: 2px;
      left: 2px;
      font-size: 16px;
      line-height: 16px;
      padding: 2px;
      margin: 0;
      background-color: green;
    }

XHTML

<!– 动画合成层 –> <div class=”animating”>composited
animating</div> <ul> <!– assume overlap –> <li
class=”box”> <!– assume overlap –> <p
class=”inner”>asume overlap, 因为 squashingClippingContainerMismatch
无法回落</p> </li> … </ul>

1
2
3
4
5
6
7
8
9
10
11
<!– 动画合成层 –>
<div class="animating">composited animating</div>
<ul>
  <!– assume overlap –>
  <li class="box">
    <!– assume overlap –>
    <p class="inner">asume overlap, 因为 squashingClippingContainerMismatch 无法压缩</p>
  </li>
  
  …
</ul>

demo
中,.animating 的合成层在运行动画,会造成 .inner
元素因为上文介绍了之 assumedOverlap
的原故,而受提升为合成层,同时,.inner 的父元素 .box 设置了
overflow: hidden,导致 .inner 的合成层因为
squashingClippingContainerMismatch
的缘由,无法回落,就起了层爆炸的题材。

图片 28

这种场面平时于咱们的事情中还是非常常见的,比如 slider + list
的布局,一旦满足了无法进行层压缩的状,就很易并发重叠爆炸的题目。

解决层爆炸的题目,最佳方案是打破 overlap
的原则,也就是说让别因素不要跟合成层元素重叠。对于上述的示范,我们可以
.animation 的 z-index 提高。修改后
demo

CSS

.animating { … /* 让其他因素不跟合成层重叠 */ position: relative;
z-index: 1; }

1
2
3
4
5
6
7
.animating {
  
  …
  /* 让其他元素不和合成层重叠 */
  position: relative;
  z-index: 1;
}

此时,就只有 .animating 提升为合成层,如下:

图片 29

还要,内存占用比较之前为下滑了森。

图片 30

设给抑制视觉需要相当因素,其他因素必须使挂于合成层之上,那应该尽量避免无法层压缩情况的面世。针对上述示范中,无法层压缩的事态(squashingClippingContainerMismatch),我们得拿
.boxoverflow: hidden
去丢,这样虽可用浏览器的重叠压缩了。修改后
demo

此刻,由于第一独 .box 因为 squashingLayerIsAnimating
的案由无法回落,其他的还吃缩减至了共。

图片 31

与此同时,内存占用比较前面也回落了多。

图片 32

末尾建议

最后

事先无线支付时,大多数人口且怪喜爱使用 translateZ(0)
来拓展所谓的硬件加速,以提升性能,但是性能优化并无所谓的“银弹”,translateZ(0)
不是,本文列有底优化建议为不是。抛开了针对页面的具体分析,任何的性能优化都是站不住脚的,盲目的运用部分优化措施,结果也许会见弄巧成拙。因此具体的夺分析页面的实际性能表现,不断的精益求精测试,才是是的优化途径。

参考资料

参考

图片 33

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图