ブラウザのレンダリング処理をカーディング
まず、ブラウザ要求、ロードで簡単に見、ページの一般的なプロセスをレンダリングします:
- DNSルックアップ
- TCPコネクション
- つまり、HTTPリクエストに応じて、
- サーバーの応答
- クライアント側のレンダリング
ここでは主なクライアントが起動櫛をレンダリングする、(レンダリングスレッドは、要求、ページのロードを受信して、ページをレンダリングする)コンテンツを取得し、おそらくブラウザのカーネルから次のステップに分けることができ、レンダリング:
- HTMLの構文解析、DOMツリーの確立
- 建設(CSSコードはツリーデータ構造に解析し、次いで合わせたDOMツリーをレンダリングに結合される)ツリーを解析CSSをレンダリング
- 各要素の大きさを計算する責任ツリーレンダリングレイアウト(レイアウト/リフロー)の位置
- 、木(塗料)を描画する描画ピクセル情報ページを描きます
- ブラウザは、GPUのレイヤにメッセージを送信する(GPU処理:3Dレンダリング、等のために最大1つで)、GPUは、(合成)合成の層となり、画面上に表示されます。
マップへの参照(webkitのメインプロセスをレンダリング):
ここでは、理解容易にするため、いくつかの概念を説明するために:
DOMツリー:ブラウザは、ツリーデータ構造にHTMLを解析します。
CSSルールツリー:CSSブラウザはツリー構造にデータを解析します。
ツリーをレンダリング:複合DOMツリーとCSSOMをレンダリング生成します。
レイアウトは:レンダリングツリーを使用すると、ブラウザは、これにより、画面内の各ノードの位置を計算するために、彼らの所属としてだけでなく、各ノードのCSS定義をノードページを知っている必要があります。
絵:グラフィックスカードで働い規則に従って、内容が画面上に描かれました。
リフロー(リフロー):ブラウザがビットの変更があった部分を見つけるのレイアウトに影響を与え、あなたは戻って再レンダリングする必要があり、専門家は、ロールバックプロセスは、リフローと呼ばれていると言います。リフロー<HTML>再帰ルートフレームダウンから開始し、すべてのノードが順次形状および位置を計算しました。リフローはほとんど避けられません。今人気な折りたたみ式ツリーとして効果のいくつかは、拡大画面上でリフローブラウザの原因となります、など、(本質的要素を表示し、隠されました)。マウスオーバー、限りこれらは、フットプリントの特定の要素、位置決め方法、余白や他のページの特性の変化を引き起こした行為として、それは内部の原因となり、さらには周りのページ全体を再レンダリング......上をクリックします。通常、我々は、彼らのすべてがお互いに影響を与え、リフローするコードのどの部分最後にブラウザを推定することはできません。
リペイント(再描画)は:それは周りのプロパティまたは内部のレイアウトに影響しない場合に再描画する画面の一部なので、要素の背景色、文字色、境界線の色などを変更するが、要素の形状が変更されていません。
注意:
- 表示:ノードのどれツリーをレンダリングするために添加されず、視認性:隠された
意志、したがって、ノードは、ショーの始まりでない場合、ディスプレイにセット:いずれも良好ではありません。 - 表示:どれもリフローをトリガしません、と可視性:位置に変化が見られないので、隠されただけで、再描画をトリガーします。
- このようなスタイルの要素を変更するなど、いくつかのケースでは、ブラウザは、すぐに再描画や、一度リフローしませんが、このような操作の回数を蓄積し、その後も非同期リフローまたは増分非同期リフローと呼ばれ、リフローを行います。しかし、いくつかのケースでは、など、ウィンドウのサイズを変更するフォントのデフォルトページを変更します。これらの操作のために、ブラウザは、すぐにリフローになります。
理解するためにマップを見て再び参照:
二つのリンクを慎重に分離し、コンセプトの他の側面は、参照のメモして説明しました:
JavaScript
:JavaScriptのアニメーションを達成するために、DOM要素の操作。Composite(渲染层合并)
:ページのレンダリングのDOM要素は、複数の層で行われます。層のそれぞれに描画処理が終了した後、ブラウザは全ての層は、層に適切な順序であったであろうし、画面に表示されます。層の順序は、エラーをマージ後、異常な表示要素の原因となるので、重複ページ要素の位置のために、このプロセスは、特に重要です。
実用的なシナリオでは、大まかに3つの一般的なレンダリングプロセスが存在するであろう(レイアウトとペイント工程は注意が地図の部分を参照して理解することができる、回避可能です)。
複合
層を学びます
注:まず、この議論はWebKitのある、実装のクロームの詳細ではなく、ウェブプラットフォームの機能について説明し、その内容はここに提示し、必ずしも他のブラウザには適用されません。
- ハードウェアアクセラレーションパスと、古いパスソフトウェア(古いソフトウェアパス):Chromeは二つの異なるレンダリングパス(レンダリングパス)を持っています
- GPUにアップロード(サブツリーレンダーの責任)レンダー(責任DOMサブツリー)とGraphicsLayer、質感(テクスチャ)としてのみGraphicsLayerです:クローム異なる層の種類があります。
- テクスチャとは何ですか?なお、画像メモリ(例えばにおけるVRAM GPU)ビットマップ画像(のBitmapImage)とメインメモリ(例えば、RAM)から移動するように考えることができます。
- GPUからページコンテンツのチャンクを取得するにはクロームの質感。非常に単純な矩形グリッドにテクスチャを適用することによって、容易に異なる位置(位置)及び変形(変換)を一致させることができます。これは、動作原理3DCSSあり、そしてそれはまた、高速スクロールのために非常に有効です。
全体像:
実際には、Chromeの層のいくつかの種類があります。
- 対応するDOMのサブツリーに責任がある層を、レンダリングRenderLayers
- 対応RenderLayersサブツリーを担当してGraphicsLayersグラフィック層、。
在浏览器渲染流程中提到了composite概念,在 DOM 树中每个节点都会对应一个 LayoutObject,当他们的 LayoutObject 处于相同的坐标空间时,就会形成一个 RenderLayers ,也就是渲染层。RenderLayers 来保证页面元素以正确的顺序合成,这时候就会出现层合成(composite),从而正确处理透明元素和重叠元素的显示。
某些特殊的渲染层会被认为是合成层(Compositing Layers),合成层拥有单独的 GraphicsLayer,而其他不是合成层的渲染层,则和其第一个拥有 GraphicsLayer 父层公用一个。
而每个GraphicsLayer(合成层单独拥有的图层) 都有一个 GraphicsContext,GraphicsContext 会负责输出该层的位图,位图是存储在共享内存中,作为纹理上传到 GPU 中,最后由 GPU 将多个位图进行合成,然后显示到屏幕上。
如何变成合成层
合成层创建标准
什么情况下能使元素获得自己的层?虽然 Chrome的启发式方法(heuristic)随着时间在不断发展进步,但是从目前来说,满足以下任意情况便会创建层:
- 3D 或透视变换(perspective transform) CSS 属性
- 使用加速视频解码的 <video> 元素 拥有 3D
- (WebGL) 上下文或加速的 2D 上下文的 <canvas> 元素
- 混合插件(如 Flash)
- 对自己的 opacity 做 CSS动画或使用一个动画变换的元素
- 拥有加速 CSS 过滤器的元素
- 元素有一个包含复合层的后代节点(换句话说,就是一个元素拥有一个子元素,该子元素在自己的层里)
- 元素有一个z-index较低且包含一个复合层的兄弟元素(换句话说就是该元素在复合层上面渲染)
合成层的优点
淘宝的栗子举的很详细,值得一看,里面提到了一旦renderLayer提升为了合成层就会有自己的绘图上下文,并且会开启硬件加速,有利于性能提升,里面列举了一些特点
- 合成层的位图,会交由 GPU 合成,比 CPU 处理要快
- 当需要 repaint 时,只需要 repaint 本身,不会影响到其他的层
- 对于 transform 和 opacity 效果,不会触发 layout 和 paint
注意:
- 提升到合成层后合成层的位图会交GPU处理,但请注意,仅仅只是合成的处理(把绘图上下文的位图输出进行组合)需要用到GPU,生成合成层的位图处理(绘图上下文的工作)是需要CPU。
- 当需要repaint的时候可以只repaint本身,不影响其他层,但是paint之前还有style, layout,那就意味着即使合成层只是repaint了自己,但style和layout本身就很占用时间。
- 仅仅是transform和opacity不会引发layout 和paint,那么其他的属性不确定。
总结合成层的优势:一般一个元素开启硬件加速后会变成合成层,可以独立于普通文档流中,改动后可以避免整个页面重绘,提升性能。
性能优化点:
- 提升动画效果的元素 合成层的好处是不会影响到其他元素的绘制,因此,为了减少动画元素对其他元素的影响,从而减少paint,我们需要把动画效果中的元素提升为合成层。
提升合成层的最好方式是使用 CSS 的 will-change属性。从上一节合成层产生原因中,可以知道 will-change 设置为opacity、transform、top、left、bottom、right 可以将元素提升为合成层。
- 使用 transform 或者 opacity 来实现动画效果, 这样只需要做合成层的合并就好了。
- 减少绘制区域 对于不需要重新绘制的区域应尽量避免绘制,以减少绘制区域,比如一个 fix 在页面顶部的固定不变的导航header,在页面内容某个区域 repaint 时,整个屏幕包括 fix 的 header 也会被重绘。
而对于固定不变的区域,我们期望其并不会被重绘,因此可以通过之前的方法,将其提升为独立的合成层。减少绘制区域,需要仔细分析页面,区分绘制区域,减少重绘区域甚至避免重绘。
利用合成层可能踩到的坑
- 合成层占用内存的问题
- 层爆炸,由于某些原因可能导致产生大量不在预期内的合成层,虽然有浏览器的层压缩机制,但是也有很多无法进行压缩的情况,这就可能出现层爆炸的现象(简单理解就是,很多不需要提升为合成层的元素因为某些不当操作成为了合成层)。解决层爆炸的问题,最佳方案是打破 overlap 的条件,也就是说让其他元素不要和合成层元素重叠。简单直接的方式:
使用3D硬件加速提升动画性能时,最好给元素增加一个z-index属性,人为干扰合成的排序,可以有效减少chrome创建不必要的合成层,提升渲染性能,移动端优化效果尤为明显。
在这篇文章中的demo可以看出其中厉害。
用chremo打开demo页面后,开启浏览器的开发者模式,再按照如图操作打开查看工具:
开启 Rendering 的Layer borders后 观察点击为动画元素设置z-index复选框
的页面提示变化:
上图中可以明显看出:页面中设置了一个h1标题,应用了translate3d动画,使得它被放到composited layer中渲染,然后在这个元素后面创建了2000个list。在不为h1元素设置z-index的情况下,使得本不需要提升到合成层的ul元素下的每个li元素都提升为一个单独合成层(每个li元素的黄色提示边框),最终会导致GPU资源过度消耗页面滑动时很卡,尤其在移动端(安卓)上更加明显。
如上图操作选中为动画元素设置z-index
,可以看出ul下的每个li都回归到普通渲染层,不再是合成层也就不会消耗GPU资源去渲染,从而达到了优化页面性能优化的目的。
大家可以用支持『硬件加速』的『安卓』手机浏览器测试上述页面,给动画元素加z-index前后的性能差距非常明显。
最后
実際のフロントエンドの開発で特にモバイル側の開発、多くの小さなパートナーが同様のtranslateZ(0)の性能を向上させ、ページの動的効果を最適化する目的を達成するために、いわゆるハードウェアアクセラレーションに属性が、それでもすべてに注意を払うに持っているを使用してのようなものですあまりにも遠く、ピットの上に乗らないでくださいまた、アプリケーションのハードウェアアクセラレーションに注意してください。
合成層について言及は慎重に次の資料(特に最初の3 OH)の下で学ぶことができ、より具体的かつ詳細に説明します。
最後に、私は猛烈な技術を探求する道を遵守あなたは常に技術を愛したいです!
参考記事:
ワイヤレスパフォーマンスの最適化:コンポジット
画面にDOM
CSS GPUアニメーション:それは右行う
複合のウェブ最適化
(複合)滞留層の合成を
CSS3のハードウェアアクセラレーションピット