『Webフロントエンド ハイパフォーマンス チューニング』学習メモ
Ch1 Web performanceとは何か
- performance: userの様々な振る舞いにWeb pageが応答する速さ
- Web page内でのinteractionのperformanceの最適化を目指す
Ch2 browserのrenderingの仕組み
- 対象とするrendering engine
- history
- WebKit系のrendering engineを見る
- rendering engine: browserの内部で利用するHTMLの描画engine
- HTML, 画像ファイル, CSS, JavaScriptなどの各種resourceを読み取って,画面上の実際のpixelとして描画
- JavaScript engine
- V8など
- V8はNode.jsでも使われている
- V8など
- WebView: browserと異なり,Web pageの表示のみを行うcomponent
- online contentsをapplication内で表示/application内のcontentsを再installすることなしにdynamic updateのため.
- WKWebView > UIWebView
- browserのrenderingの流れ
- HTML, CSS, JavaScript, HTTPなどの周辺要素が相互に関連し合って進むため,複雑
- 4つの工程からなるrenderingが始まって,最終的に描画されるまで: Frame
- resourceの読み込み: Loading
- browserが, URLからHTMLを読み込んで,そこからさらにrenderingに必要な付属するresourceを読み込んで解釈
- resourceのdownload + resourceのparse
- resource: HTML/CSS/JavaScript/{JPEG, PNG, GIF, SVG} file
- resourceの取得のためのnetwork protocol
- 各resourceの読み込み
- HTMLの読み込み
- URLからHTTP request → HTTP responseとしてHTMLを取得
- → 取得したHTMLを解釈し,DOM(Document Object Model) treeを構築
- DOM: HTMLのDocumentを表現するObject.rendering engineが利用する木構造を持つ内部表現.
- DOM treeへの変換過程で,画像やCSSなどのDocumentに紐づくresourceの取得や読み込みを行う
- DOM tree: JavaScriptからアクセス〇 → DOM操作
- process
- 字句解析によるtokenのlist化
- 構文木内にあるJavaScriptを実行しつつDOM treeの構築
- img: 画像.link: CSS.script: JavaScript.
- CSSの読み込み
- HTMLの読み込み
- browserが, URLからHTMLを読み込んで,そこからさらにrenderingに必要な付属するresourceを読み込んで解釈
- JavaScript 実行 -Scripting
- JavaScriptの実行: 最初にJavaScriptファイルを読み込んだとき + DOMイベントが発火しevent listenerが起動するとき
- 字句解析と構文解析
- 字句解析: source code → token list
- 構文解析: token list → 抽象構文木
- 抽象構文木: JavaScriptの文法に則った形で表現される木構造のdata
- compile
- 実行
- JavaScript内では,DOM APIを通じてDOM treeを操作
- 後続のRendering, Painting phaseやLoading phaseを引き起こす
- Layout tree構築 -Rendering
- Calculate Style + Layout
- Calculate Style
- Layout
- 要素の大きさ,margin, padding, 位置,z軸の位置を計算
- rendering結果の描画 -Painting
- Paint
- 内部の低レベルな2D graphic engine向けの命令の列(Display List)を,Layerごとに生成
- browserによって,組み込むgraphic engineが異なる
- bottleneckにはならない
- Rasterize
- 生成された命令から,pixel(bitmap)へと描画
- overhead大きい
- layerという単位で1枚ずつ描画
- layer: overwrapして表示するcontentsがあるときに生成
- 描画済みのlayerを再利用して,再renderingが素早く容易になる
- Composite(複合,合成) Layers
- pixelにしたlayerを合成して最終的なrendering結果を生成
- 3Dの処理などはGPU.ほかはCPU.
- Paint
- 再rendering
- DOM eventにより発生
- JavaScriptのコードにより,どのphaseを引き起こすか知ることがimportant
Ch3 tuningの基礎
- 闇雲なtuningの害
- trade off: developerの時間的resource.コードの単純さ.
- best practice
- HTTP requestを減らす
- CDNを使う
- Expires headerを設定する
- componentをgzipする
- style sheetは先頭に置く
- scriptは最後に置く
- CSS expressionの使用を控える
- JavaScriptとCSSは外部ファイル化する
- DNS lookupを減らす
- JavaScriptを最小化する
- redirectを避ける
- scriptを重複させない
- ETagの設定を変更する
- Ajaxをcache可能にする
- ×推測,〇計測
- bottleneckの解消がimportant
- 目指すべき指標を設定する
- performance metrics: RAIL
- user中心のperformance model
- Web page以外にも,複雑なinteractionやanimationを含むWeb applicationやHybrid applicationにも適用できる
- Response, Animation, Idle, Load
- Response: 100 ms
- userが感じられる視覚的な変化
- over 100 msなら,処理中を意味するindicatorの表示が〇
- 指のtouchやscrollはAnimationと同じく16 ms以内が必要
- Animation: 16 ms
- 連続して行われるframeの中で1 frameの処理時間の目安
- frame: Scripting, Rendering, Painting
- 16 ms → 60 FPS(Frames Per Second)を満たす
- frame中のJavaScriptの処理時間は6 ms以内
- Idle: 50 ms
- Idle状態で実行されるJavaScriptの処理時間
- Load: 1000 ms
- 1000 ms以内にsplash screenを表示して,そのほかのresourceの読み込みは遅延でも〇
- cacheやloading 画面の表示で,各種resourceの読み込みを遅らせるのが〇
- performance metrics: RAIL
- 計測手段
- Chrome DevToolsなどdeveloper toolによる計測
- Web page内の細かな計測や解析を行うのに有効
- Web pageがどのように処理されてRenderingに至るのかを詳細・多角的にみられる
- performanceのbottleneckの原因箇所の調査に有効
- 継続的かつ定量的な計測には向かない
- JavaScriptによる計測
- performanceのmetricsの収集・算出の自動化
- userの環境にばらつきがあるcaseで特に有効
- performance診断tool
- performanceが適切かどうか,performance改善のためのtechniqueをadvice
- 継続的監視
- 改修を重ねていくときにperformanceの問題を常に確認する必要がある
- Chrome DevToolsなどdeveloper toolによる計測
- Chrome DevToolsなどdeveloper toolによる計測
- AndroidでのChrome DevToolsの利用方法
- PCとAndroidをUSBで接続する
- WebViewを使う場合
- iOSでのWeb inspectorの利用
- Chrome DevToolsの主要機能
- Network panel
- networkを通じたresource取得のtimelineを細かく見る
- blue line: DOMContentLoaded
- 遅い場合はscriptによる読み込みブロックなどの問題
- red line: Load event
- 遅い場合はresourceの容量が過大
- 回線状況の再現も〇
- 個別のresourceの取得時間: timeline上の表示にカーソルを合わせる
- Connection SetupやRequest/Responseの内容
- Waiting(TTFB)が長いときは,サーバ処理に時間がかかっている
- Performance panel
- page loadや操作に関するすべてのeventを分析〇
- frame chart
- blue/red lineはNetworkと同じ
- green line: 最初のPaintが発生するtiming(page上になんらかの表示が反映されるtiming)
- 特に時間のかかっている処理の割り出しに使う
- profileの取得: Performance panelの記録
- Rendering engine内のほとんどすべてのphaseのprofileを細かくとることができる
- Memory panel
- memory leakの検知やmemoryの使い過ぎの把握のため
- heap snapshot, memory割り当ての確認ができる
- AndroidでのChrome DevToolsの利用方法
- JavaScriptによる計測
- Navigation Timing APIによる計測
- browserのnavigation時の詳細なperformance情報を取得できる
- browserの各段階の処理時間を計測〇
- 以前のWeb pageのunloadの時間など,Web serverでは検知できない情報を得られる
- Objectのpropertyの差を求め,処理時間を算出
- timing Objectは参照するtimingに注意
- navigation Objectの内容も合わせて見る
- どのようなnavigationか
- User Timing APIによる計測
- 任意の処理にかかる時間を計測〇
- interactionなど必ずしも計測地点を機械的に宣言できない処理の計測
- performance
- mark()
- measure()
- getEntriesByName()
- 任意の処理にかかる時間を計測〇
- Resource Timing APIによる計測
- 個別のresourceの取得にかかっている時間の統計情報を取得
- redirectにかかる時間
- DNS lookupにかかる時間
- network connectionの確立にかかる時間
- HTTP responseを受け取るのにかかる時間
- Network panelとほとんど同じものが対象
- PerformanceResourceTiming Object
- 個別のresourceの取得にかかっている時間の統計情報を取得
- Performance Observerによる監視
- これから起こる処理のperformance informationを指定して監視
- 柔軟にperformance informationを取得
- SPAなどinteractionを多く持つようなWeb pageでのperformanceも容易に取得〇
- 記録・解析のためにreal timeでserverに送信も〇
- modern browserの中では,Google Chromeのみ対応
- 高精度なtimestampを得る
- Navigation Timing APIによる計測
- performance diagnostics tools
- performanceの継続的監視
- New Relic Browser
- JavaScriptをWeb siteに埋め込む
- New Relic Browser
Ch4 resource読み込みのtuning
- resource読み込みの流れ
- HTML fileから始まるresourceのgraphを構築しつつ,network protocolを通じてresourceを取得・parse
- TCP/IP + HTTP/1.1で考える
- HTML/CSS/JavaScriptを最小化する
- 余計なbyte列を除去する各tools
- deploy前で自動化する
- JavaScript libraryは最小化されているものを使っても〇
- 余計なbyte列を除去する各tools
- proper image typeを選択
- image fileを最適化
- 各toolsを,wrapper tool, task runnerやbuild toolなどから使うことも多い
- Web fontも最適化可能
- CSSのimportを回避
- HTTP requestを減らすという原則 + 直列な取得・読み込みを避けるため
- toolやメタ言語で結合する
- JavaScriptのsyncな読み込みを避ける
- JavaScriptのdocument.write()はDOM treeの構築に影響を与えるため,script要素はdocumentのparseやCSS fileの読み込みをブロックする
- JavaScriptをasyncに読み込む
- defer attribute
- JavaScript fileは,DOM treeが構築されてから初めて実行
- DOMContentLoaded eventの発火前に実行
- 実行順を保証
- JavaScript fileは,DOM treeが構築されてから初めて実行
- async attribute
- JavaScriptのdownload時点で実行される
- 実行順を保証しない
- 依存関係は,ファイルの結合などで解消が必要
- JavaScriptでscript要素をasyncに読み込む
- 読み込むtimingを細かく制御したい場合など
- async 読み込みの利用方針
- asyncが一番performance〇
- asyncがダメならdefer
- deferもダメなら通常のscript要素
- defer attribute
- device pixel比ごとに読み込む画像を切り替える
- srcset
- さらにresponsive対応をするなら,pictureやsizes
- CSSのmedia queryを適切に指定する
- CSS spriteを使って複数の画像をまとめる
- HTTP requestを減らす
- まとめた画像の一部を切り取って表示
- CriticalCSSで最初の描画を最適化
- resourceを事前読み込みしておく
- Gzip圧縮を有効にする
- CDNを用いてresourceを配信する
- Akamai, Cloudflareなど
- domain sharding
- not redirect
- directoryの名前で終わらず,/をつけるかファイル名を明示する
- directoryの名前で終わると,/をつけたURLにredirectされる
- directoryの名前で終わらず,/をつけるかファイル名を明示する
- browserのcacheを活用
- Expires header
- 強いcache
- Apacheでの指定方法
- HTTP response headerを確認するとわかる
- server/clientで時間設定がずれていると×
- Cache-Control header
- 強いcache
- max-age
- Apacheでの指定方法
- Expires/Cache-Control headerの使い分け
- Cache-Control headerが優先される
- Expires headerは古い
- URLにtokenを付加する
- 強いcacheを疑似的に消す
- PHPなどのserver sideで付加することがほとんど
- 弱いcacheの活用
- 条件つきHTTP requestを使う
- Last-Modified headerの設定
- ETag headerの設定
- Entity Tag(version)で表現
- Last-Modified/ETag headerの使い分け
- ETagが優先される
- Apacheでの指定方法
- 複数台のWeb serverのときは,ETagが変わってしまうため対応が必要
- ETagの柔軟性が不要なら,ETagを付加せずLast-Modifiedのみ指定
- cacheの使い分け
- 静的なresourceは強いcache
- まず強いcacheを使えないか判断し,だめなら弱いcache
- Expires header
- Service Workerの使用
- JavaScriptからcacheの制御を柔軟に実行可能
- Web Workerの一種で,main threadとは別threadで動作
- Web pageとWeb server間でproxyのように動作し,resourceをcacheから取得するかWeb serverから取得するか決定
- Service Workerの導入
- 廃止されるApplication Cacheの代替になる
- HTTP/2の利用
- SPDY protocolがbase
- SPDY protocol: resource読み込みのlatencyの削減を目的にGoogleが開発
- binary化したprotocol
- HTTP/1.1: text baseの通信
- 効率〇
- HTTP/1.1のsemanticsの再利用
- HTTP/1.1とTCPの間に挟まって通信を効率化するような形
- requestとresponseの多重化
- browserの同時connection数のlimitなし
- HTTP headerの圧縮(HPACK)
- RFC7541
- 以前送ったHTTP headerの差分のみをお互いに送る
- 無駄が減る.requestごとの効率up
- HTTP/2 protocolはTLSが事実上必須
- 速度は問題ないケースもある
- HTTP/2で無意味になるtechnique
- HTTP request数を減らしたり,同時接続数の制限を疑似的に増やす必要がなくなる
- HTTP/2 対応 reverse proxyの利用
- clientからのaccessをHTTP/2 serverが処理し,実際のcontents配信はHTTP/1.1 serverが行う構成を取れる
- SPDY protocolがbase
- QUIC protocol
- build tool
- ファイルの依存関係を解決し,複数のファイルをまとめる目的
- task runnerも同等の用途で使われる
- tuningのためのtechniqueの自動化に必要
- TypeScriptやBabelのtranspileや,buildまでの経路の複雑化などから,build toolは不可欠になってきている
Ch5 JavaScript実行(Scripting)のtuning
- HTML5になり,文書だけでなくapplicationを表現するplatformになった.
- 文書と構造: HTML, CSS ←→ 動的な側面: JavaScript
- JavaScriptの実行model
- UI thread
- tab1つにつき1つのUI thread(main thread)
- JavaScriptの実行だけでなく,rendering engineの様々な処理が実行
- Layoutの計算,rendering処理,DOM eventの発火など
- event loopと実行queue
- JavaScriptはevent loopというmodelで動作するため,single threadでの動作にもかかわらず,複数の処理を同時に実行できる
- responseの受け取りなどの継続する処理は,asyncで動作するcallbackの受け渡しやevent listenerによる
- networkなど処理待ちの時間は,タスクを一度終了しUI threadに制御を戻す.処理の再開時にはじめてUI thread上での処理が始まる.
- 例外
- alert(), confirm(), prompt(), sync XMLHttpRequest
- JavaScriptはevent loopというmodelで動作するため,single threadでの動作にもかかわらず,複数の処理を同時に実行できる
- UI thread
- JavaScriptのbottleneckを特定する
- Performance panelによる計測
- rendering engineの行うほとんどの処理のprofileを取れる
- JavaScript, UI threadのrendering, DOM eventの処理など
- JavaScriptでは,どの関数でどのくらい時間がかかっているか細かくわかる
- performance diagnosticsなら,まずはPerformance panelでprofileを取る
- rendering engineの行うほとんどの処理のprofileを取れる
- 各処理の確認方法
- 警告箇所と,ほかの処理の妨げになっているところや明らかに処理時間が長いものを見ていく
- Performance panelによる計測
- GCを避ける
- requestAnimationFrame()などのときに,問題になる
- 検知: Performance panelでprofileを取る
- 防ぐ: 新しいObjectを生成しないか,必要なObjectや配列を予め生成しておく
- memory leakを防ぐ
- importance
- performanceやapplicationの安定性のためにimportant
- desktopでもswapで遅くなるし,mobileではapplicationがcrashする
- detection
- Performance panelでprofileを取る
- heapの3点観測
- heap snapshotを3つとる
- Summary viewの見方
- 黄色のObject: JavaScriptから参照されているObject
- 赤: documentのDOM treeから分離したDOM treeに含まれているDOM要素
- console.log()によるmemory leak
- log()以外も,consoleに値を解析して表示する類のものは,特殊な参照がつく
- debug処理の除去の自動化ができる
- DOM leak
- DOM tree自体もleakする
- DOM leakの検知
- importance
- WeakMap, WeakSet
- weak reference: GCでは利用されていると見られない
- WeakMap: あるObjectの拡張や,private memberを持ちたいときに使える
- WeakSet: あるObjectにflagを立てたいときに使える
- 利用して〇なら最初から利用する
- Web Workersの利用
- codeの複雑化,thread生成costなどのtrade offあり
- 利用方法
- Web WorkersのthreadとUI thread間の通信: message passing(asyncにデータを通信し合う
- postMessage(), event listener
- 共有ではなくcopy
- Web WorkersのthreadとUI thread間の通信: message passing(asyncにデータを通信し合う
- multi Web Workersを生成する
- multi coreで並列計算
- navigator.hardwareConcurrencyを参照してコア数を取り,それに応じたWeb Workersを生成する
- 論理的なコア数が見える
- Transferableを利用
- copyとcopyのoverheadを回避
- 所有権が移動する
- Transferableを実装しているObject
- ArrayBuffer: 型つき配列のdata storage
- MessagePort: ほかのdocumentとの通信のために使う
- 制限
- 使えないObject
- DOM要素,document Object, window Object, parent Object
- → 純粋なデータ処理のみをWeb Workerで行う
- 使えないObject
- asm.jsによるJavaScript高速化
- 高速実行のためのJavaScriptのsubset language
- specification
- 計算はすべてstatic typing
- 計算で使える型はint, double, floatのみ
- asm.js module内部では仮想的にGCが利用不可
- asm.js形式のコードを書きだすtranspilerによって処理を記述する想定
- いずれWebAssemblyにreplaced
- WebAssembly
- より高速なloadと実行を目的として各browser vendorによって策定されている,browser上で実行可能なbinary format
- JavaScriptの一部の機能を代替
- merit, compared to asm.js
- load time短縮
- parseの簡略化
- heap sizeの制限緩和
- memoryに対する柔軟な読み書き
- SIMD.jsの利用
- 高頻度で発火するeventの抑制
- scroll, resize, touchmoveなど
- setTimeout()やrequestAnimationFrame()で,ある一定の頻度でのみ実際の処理を行うようにする
- そのほか,視差効果やscroll event listenerなど
- mobile端末でのclick eventの遅延をなくす
- meta要素によるviewportを適切に設定する
- FastClickやTappy libraryを使っても〇
- Passive Event Listenerでscrollのperformanceを改善する
- event.preventDefault()が無効になることを保証
- capture phaseでevent listenerを呼び出し
- browserでのsupportの確認処理
- scroll performanceの改善以外にも,event listenerがinteractionをブロックする時間が気になるときには検討〇
- setImmediate()のasync 実行
- setTimeout()は,指定した時間の後にasync実行
- ↑ ずれがある
- ←→ setImmediate()は,UI threadがidleになったらすぐに実行
- clearImmediate()で解除
- polyfill libraryのsetImmediate.jsで使える
- setTimeout()は,指定した時間の後にasync実行
- idle時処理を使う
- requestIdleCallback()
- cancelIdleCallback()で解除
- page表示状態を確認する
- 状態に応じて,animationのon/offなどを行う
- 正確なpage viewの測定にも使う
- Page Visibility API
- document.hiddenを参照
- visibilitychange event
- document.visibilityState
- 無駄なForced Synchronous Layoutを減らす
- DOM操作→関連するDOM要素のLayout情報を参照で,Forced Synchronous Layoutが引き起こされる
- Recalculate StyleとLayoutがsyncに処理される
- JavaScriptともsyncに実行
- Layoutに影響する操作
- style attributeやstyle propertyを通じて要素の大きさや座標にかかわる操作をする
- DOM要素のclass属性を変えて,当たるstyleを変更して要素の大きさや座標を変更する
- DOM treeの構造に変更を加える操作(DOM要素の追加・削除など)
- 計測
- Layout Thrashingを避ける
- loop中でFSLを繰り返し起こしてしまうこと
- FSLを防ぐ
- DOM 操作の前にLayout情報を参照する
- requestAnimationFrame()で計算済みのLayout情報を参照する
- DOM操作→関連するDOM要素のLayout情報を参照で,Forced Synchronous Layoutが引き起こされる
- DocumentFragmentの追加
- Web pageのdocumentの断片を表す
- DOM treeへのDOM要素の追加を速くできる
- 複数のDOM要素を格納〇
- Intersection Observerで効率的に交差を検知する
- あるDOM要素と親要素が視覚的に交差しているか監視
- 使い方
- not supportedなら,scroll eventで処理したりしないといけない.問題がある.
- canvas要素の2D Context animation
- requestAnimationFrame()を活用する
- setTimeout()やsetInterval()の課題
- proper timingでcallbackの呼び出しがdifficult
- requestAnimationFrame()によるanimation
- 自動的に呼び出しtimingを最適化
- 指定したcallbackを,browserのrenderingの処理に合わせて,proper timingで呼び出し
- setTimeout()やsetInterval()の課題
- JavaScriptからCSS Transitionを使う
- animationの進行中はJavaScriptのコードは一切実行されない
- requestAnimationFrame()とは異なり,JavaScriptがbottleneckにはならない
- UI threadとは別のthreadで実行
- rendering engine内部で最適なtimingで実行される
- animationの進行中はJavaScriptのコードは一切実行されない
- WebGL
- WebCL
- 小さな最適化
- 有意味でないことが多い
- まずはbottleneckの解析
- 次は,アルゴリズム・データ構造や基礎技術の改善
Ch6 Layout tree構築(Rendering)のtuning
- Rendering: Calculate Style + Layout
- interactionの高速化にもつながる
- Layout tree構築の流れ
- Layout tree構築におけるperformanceの計測
- Performance panel
- Recalculate Style
- Elements Affected
- Layout
- Nodes that need layout
- Layout root
- Recalculate Style
- Performance panel
- 高速なCSS selectorの記述
- BEMを用いる
- 設計・保守しやすさを上げる + performance〇
- BEM: Block, Element, Modifier
- Block: page内を構成するひとかたまり.header, footer, 記事など.
- Element: Blockを構成する要素
- Modifier: BlockやElementの見た目や振る舞いを拡張
- 1つのclass selectorのみでCSS selectorを宣言する
- CSS selectorのmatching処理を避ける
- DOM要素のstyle propertyを直接変更すると,matching処理を回避できる
- 必ずそうするべきというわけではなく,高速なperformanceが必要なanimationやinteractionのときのみ
- 利用していないCSS rule setを減らす
- UNCSS
- build toolとの組み合わせも〇
- UNCSS
- media queryを指定する
- 不要なrule setをまとめて除外できて〇
- DOM要素のstyle propertyを直接変更すると,matching処理を回避できる
- Layoutを高速化する
- a.c.a Reflow
- Layoutを避ける
- Layoutの原因
- DOM要素の座標や大きさの変化
- DOM treeの構造の変化
- DOM要素のcontentの変化
- Layoutの範囲を限定する
- いずれかの条件
- svg要素
- type="text", or type="search"のinput要素
- table要素の子孫じゃなくてかついろいろ条件を満たす
- いずれかの条件
- Layoutの原因
- DOM treeから切り離して処理する
- DOM treeから離れれば,Renderingはなくなる
- remove()
- 必要になった時にappendChild()などで再挿入すればよい
- Layoutを減らす非表示
- display: none
- img要素のsizeを固定
- height, widthを指定しないと仮の大きさで1度Layoutが走る
Ch7 Rendering結果の描画(Painting)のtuning
- interactionやanimationを実装するときに頻繁に実行される
- Rendering結果の描画の流れ
- → Ch2
- 再描画(Repaint)
- CSS propertyの変更が何を引き起こすか
- CSS Triggers
- Layerの生成条件
- Layer treeが構成される
- GPUに転送されるGraphics Layerが,performanceに影響大きい
- うまく扱うと,animationを高速化できる
- Layer treeを確認する
- Performance panel
- Layer treeの詳細を確認
- 歯車 → Enable advanced paint instrumentation(slow)にチェック → profileを取得 → Frames → Layers
- Layerの範囲を確認
- Rendering optionのLayers Borders
- 描画のoverheadを解析
- Performance panelでPaint Profilerを見る
- Paint Profilerの確認方法
- GPUによって合成されるlayer
- translateZ hack
- translateZ(0)により,結果を変えずにGPUで合成できる
- position: fixedのscroll speedの改善
- body要素にtranslateZ hackを用いる問題
- translateZを使うためのrule
- Rasterizeされることが少ない要素に用いる
- 領域がそれほど大きくない要素に用いる
- 必要なときだけ用いる
- translateZを使うためのrule
- 必要なtimingだけtranslateZ hackを用いる
- JavaScriptでDOM要素のstyle propertyを指定する
- will-changeCSS propertyによるtranslateZ hackの代替
Ch8 高度なtuning
- 大量のDOM要素を扱うvirtual rendering
- なめらかなanimation
- 指標と基本的な考え方
- RAILを使う
- Rerenderingのphaseを減らす
- skip Calculate Style
- JavaScriptでDOM要素のstyle propertyを直接変更
- 不要ならDOM treeの構造やDOM属性を変更しない
- skip Layout
- transformCSS propertyの値に,translate()やscale()を使う
- skip Paint
- Paintを引き起こさないproperty
- opacity
- transform
- これらを使えない場合は仕方ない
- Paintを引き起こさないproperty
- layerの合成の最適化
- translateZ hack
- 指標と基本的な考え方
- will-changeCSS propertyによる最適化
- CSS property名を指定
- opacity, transformのみ
- scroll-positionを指定
- 要素の移動(animation)や素早いscrollに対応
- contentsを指定
- animationや変更を予想
- cacheの生成・維持を省ける
- dynamicに利用
- JavaScriptからのdynamicな利用が〇
- CSSでの宣言は,その要素が常に変更されるときのみ
- 使い方
- 最適化においては,見かけほど有用ではない
- CSS property名を指定
- CSS ContainmentでRerenderingを最適化
- CSS Containment: DOM treeの一部に封じ込め〇
- 利用方法
- layout: Layoutの封じ込め
- 副作用: floatCSS propertyでの回り込みの影響がなくなる
- paint: Paintの封じ込め
- Layoutの封じ込めとともに,大きな最適化
- 副作用3点
- style: styleの封じ込め
- 単体では使わない
- size: 大きさの封じ込め
- 単体では使わない
- layoutと併用したり,content/strictを指定して使う
- content/strict: 複数の封じ込め
- content: layout + paint + style
- strict: layout + paint + size + style
- 最も最適化の効果〇
- まずはstrictで,だめならcontent
- AMP(Accelarated Mobile Pages)
- static contentsを高速に提供
- 専用CDNやprerenderingなどで〇
Ch9 認知的tuning
- indicatorを使う
- 1sを超える処理や読み込みのとき
- 10sを超えるときはprogress barなどの進捗の表示が必要
- interface previewを使う
- indicatorより印象〇
- 処理が終わったように振る舞う
- beforeunloadで処理中の離脱へのアラート
- 無限scroll
- 同様の要素を表示するpageで使う
- userのscrollをJavaScriptで検知,pageの最下部になると,次のpageの情報を読み取って動的に読み込むべきcontentsを画面下部に追加
- 一部のRerenderingで済むため速い
- 実装上の注意
- → 5.11
- virtual renderingとの違い
- 無限scrollはvirtual renderingと併用する
- merit
- waiting time小さい
- demerit
- footer使えない
- back buttonで表示が壊れることがある
- リンクは別windowにするなど対応が必要
- 投機的なresourceの先読み
- user activityの洞察と解析が必要
- 事例
- 手段
- JavaScriptで実装したapplication levelのcacheを使う
- IndexedDB, LocalStorageなどのstorageで保存するか,もしくは単にJavaScriptの変数で保持(SPAなどのとき)
- Resource Hints API(4.11)も〇
- SPA: Single Page Application
- SPA以外は,page操作で断絶 → userの体感速度を大きく低下
- Ajaxの発展形
- library, frameworkが必要
- React.js, Angular, Vue.jsなど
Appendix SVGのperformance特性
- SVG: Scalable Vector Graphics
- XMLで表現されるVector Graphicsのformat
- browserで利用できる唯一のVector Graphics format
- HTMLと親和性がある
- img要素ではなく,svg要素で,その画像をdocument内に直接埋め込める
- tagの記述も〇
- JavaScriptでの振る舞いを追加したり,CSSで修飾もできる
- img要素ではなく,svg要素で,その画像をdocument内に直接埋め込める
- JavaScriptでSVG内の視覚的要素をanimationさせたり,event listenerを追加してinteractionを与えられる
- HTMLのanimationの問題もいくつか回避している
- JavaScriptでanimationを行う
- SMILによるanimation