ご存知のとおり、モバイル端末は、読み込みが速いだけでなく、ユーザー エクスペリエンスを必要としないコンテンツを備えている必要があります。また、迅速な応答のインタラクション、滑らかなアニメーションなど、スムーズに動作する必要があります。実際の開発では上記の効果をどのように達成するのでしょうか?
1. レンダリングパフォーマンスの分析基準を確認する
2. レンダリングパフォーマンスの基準を測定するための定規を準備する
おおよそ次のような最適化目標が得られます
1 つ目は、最初の画面レンダリング時間です。コードの圧縮、WebP 画像の使用、スプライトの使用、オンデマンドのロード、「ダイレクト アウト」、CDN など、インターネット上にはすでに多くの情報があります。 2 つ目は 16ms の最適化です。この記事では 16ms の最適化に焦点を当てます。
1. ブラウザーレンダリングの原理の概要
ほとんどのデバイスのリフレッシュ頻度は 60 回/秒 (1000/60 = 16.6ms) であり、これはブラウザーが画像の各フレームをレンダリングすることを意味します。 16 ミリ秒以内に完了する必要があります。この時間を超えると、ページのレンダリングが停止し、ユーザー エクスペリエンスに影響します。
これが上の図の
各レイヤーをラスタライズして個別にビットマップに描画します
【文字通りの解釈は非常に複雑ですが、これは昔からの真実であり、絵で明確に説明できる場合は言葉を使わないでください。 】
とはいえ、ブラウザ上で最終的に表示されるのは単なるコピーです。つまり、レイヤーは 1 つだけになります。
PhotoShop
ソフトウェアの「レイヤー」の概念と同様に、利用可能なすべてのビューレイヤー
が最終的に結合され、画像が画面に出力されますしかし実際には、ページはいくつかのルールにより対応するレイヤーに分割されます。独立しています。変更後はページに「貼り付けられる」だけなので、公開後は他の DOM のレイアウトに影響を与えません。
3D またはパースペクティブ変換 (パースペクティブ変換) CSS プロパティ
3D (WebGL) コンテキストまたは高速化された2D コンテキスト <キャンバス> 要素 プラグインを混ぜる (Flash など) 独自の不透明度で CSS アニメーションを実行するか、アニメーション Webkit を使用する 要素を変換する CSS を高速化するフィルター
要素 要素には複合レイヤーがあるノード (つまり、要素には、独自のレイヤー内に子要素があります) この要素には、複合レイヤーを含む、より低い Z インデックスを持つ兄弟要素があります (つまり、要素は、複合レイヤー) Webkit ベースのブラウザーでは、上記の状況が発生した場合、独立したレイヤーが作成されます。ブラウザーレンダリングの原則をたくさん述べてきましたが、定規なしで測定することは役に立ちません。そこで、測定する物差しを選択しましょう。Google 開発ツールのタイムラインです。
2. Google開発ツールTimelineの共通機能
1. 左上の録画をクリックすると、録画が完了すると以下が生成されます 赤い部分がフレームです。 1 フレームの周波数が 60fps を超える場合、比較的スムーズです。
2. タイムラインの下で、各モジュールの消費時間を確認でき、時間のかかる関数を見つけて関数を最適化できます。
3. 以下の手順に従って選択すると、独立したレイヤーが表示され、再描画された領域が強調表示され、不要な再描画領域を見つけて最適化することが簡単になります
その後、次の 2 色の境界線が現在のページに表示されます
黄色の境界線: アニメーション化された 3D 変換を含む要素は、新しい複合レイヤーでレンダリングされていることを示します
青色のグリッド: これらのブロックが表示されます 操作は下位レベルですChrome はこれらのチャンクを、一度に 1 つのコンテンツ チャンクを GPU にアップロードするためのユニットとして使用します。
ツールも利用可能で、ブラウザレンダリングの原理もわかっています。次のステップは、実際のプロジェクトに基づいて最適化することです。
の実行効率を最適化しますスタイル計算の範囲と複雑さを削減します
大規模で複雑なレイアウトを回避します
描画の複雑さを簡素化します描画領域を削減します
レンダリングレイヤーのマージ属性の使用を優先し、レイヤーの数を制御します
ユーザー入力イベントの処理機能をデバウンスします(モバイルデバイス)
1. 読み取りと書き込みの分離、バッチ操作
JavaScript スクリプトの実行中に取得できる要素のスタイル属性値は、すべて前のフレームからのものであり、すべて古い値です。
したがって、現在のフレームで属性を取得する前に要素ノードに変更を加えた場合、ブラウザーは最初に属性の変更を適用し、次にレイアウト プロセスを実行し、最後に JavaScript ロジックを実行します。
// 先写后读,触发强制布局 function logBoxHeight() { // 更新box样式 box.classList.add('super-big'); // 为了返回box的offersetHeight值 // 浏览器必须先应用属性修改,接着执行布局过程 console.log(box.offsetHeight); }
最適化後:
// 先读后写,避免强制布局 function logBoxHeight() { // 获取box.offsetHeight console.log(box.offsetHeight); // 更新box样式 box.classList.add('super-big'); }
2. クロージャキャッシュの計算結果(頻繁な呼び出しと計算が必要な関数)
getMaxWidth: (function () { var cache = {}; function getwidth() { if (maxWidth in cache) { return cache[maxWidth]; } var target = this.node, width = this.width, screen = document.body.clientWidth, num = target.length, maxWidth = num * width + 10 * num + 20 - screen; cache[maxWidth] = maxWidth; return maxWidth; } return getwidth; })(),
この方法に変更すると、ちゃんと動きます~10ms以上短縮されました
3. ユーザー入力イベント ハンドラーをデバウンスする
タッチされた要素が touchstart/touchmove/touchend などの入力
イベント ハンドラー関数にバインドされている場合、レンダリング層マージ スレッドはこれらがバインドされるまで待機する必要があります。処理関数の実行が完了するまで、つまりユーザーのページスクロール操作がブロックされるまで実行できず、スクロールが遅延または停止する動作が表示されます。 つまり、ユーザー入力イベントにバインドされた処理関数が迅速に実行され、レンダリング レイヤー マージ スレッドが作業を完了するための時間を確保できるようにする必要があります。
スクロール/タッチイベント処理などの入力イベント処理関数は、requestAnimationFrameより前に呼び出されて実行されます。したがって、上記の入力イベント ハンドラーでスタイル属性を変更すると、これらの操作はブラウザーによって一時的に保存されます。
その後、requestAnimationFrameを呼び出す際に、先頭でstyle属性を読み込んでしまうと、ブラウザの強制同期レイアウト操作(つまり、JavaScript段階でレイアウトを実行)が発生し、多重レイアウトが発生し、非効率になってしまいます。
最適化は次のとおりです:
window.requestAnimationFrame(function () { context.animateTo(nowPos); //需要更新位置的交给RAF });
4. 不必要な再描画を減らす
上記の続きで、ペイントの点滅をオンにすると、ブラウザがどの領域を再描画したかを確認できます。いくつかの不要な再描画領域も再描画されていることがわかりました~これら(前述)のGPU最適化を有効にしてください
タイムライン効果を直接見てください、すべて緑色になっています~ついに垂れ下がった心を手放しました
今日は、モバイル開発に関するヒントがたくさんあります。詳細については、当社の Web サイト PHP.cn をご覧ください。
関連記事:
モバイル端末開発の基礎知識(再掲)_html/css_WEB-ITnose
モバイル端末開発の基礎知識_html/css_WEB-ITnose
以上が高パフォーマンスのモバイル開発を実現する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。