プロジェクトへの依存関係の完全な弾薬を備えたボイラープレートを考えずに使用した物語、誰も使用しなかったもの、Edgeサポートが必要になったときにどのように私たちに来たのか、実際に壊れたものを英雄的に修復する方法の物語。
いいえ、長すぎます。
すべてのブラウザが属性の恐怖であり、特にその一部であるという話。
背景
ある日、同僚の1人が、AngularJSアプリケーションにコピーするときのC3デモ(グラフを表示するためのライブラリ)について、Edgeを使用すると非常に遅くなり、「遅くなる-続行します。」 さらに顧客から、現在および将来のすべての潜在的なプロジェクト。
最初に考えた-他のブラウザでチェックインします。 ChromeとFirefoxは、すべてが順調であると主張し続けました。
したがって、問題は依存関係です。 angular.module()から依存関係を削除し始めました。 まったく何も残っていなかった後、私たちの状況はすべて同じ悲惨なものでした。
次のステップは、組み込みの開発ツールパフォーマンストラッカーを使用することでした。 残念なことに、長い間、間違った場所を見て、何度も何度もさまざまなJS関数を呼び出す時間と時間を分析していました。 彼らは理解し始めました。 プロジェクトをきれいにした後、組み立てられ縮小されたCSSファイルのサイズがまだ印象的だったことはすぐに驚きました。 このプロジェクトではflex-attrライブラリが接続されていましたが、これは誰も使用せず、単に定型句からの継承によってもたらされました。
このライブラリは、Edgeを数秒間ほとんどハングアップさせるために何ができましたか?
Flex-attrは、HTMLから直接flexを操作するためのCSSルールのセットです。 私が最初にこのアプローチに出会ったのは、プロジェクトにAngular Materialを使用したときです。 その後、Angular Materialに別れを告げることになりましたが、私はこのアプローチが好きでした.CSSとSCSSのみを残してフォークを作り、LESSに移植し、新しいpostfixと画面サイズ(ブレークポイント)をオーバーライドして追加するために必要な機能を追加しました。
同僚が私たちの内部ボイラープレートを使用して、彼のプロジェクトのためにこのライブラリを受け取りました。私はそれを少し前に個人的に追加しました。 定期的に自分の足を撃たないのなら、これはどのような人生ですか? 主なものは頭の中になく、コバーンのような散弾銃からのものではありませんが、私はまだ27歳まで時間がありますので、心配することはできません。
説明からわかるように、このライブラリは属性に関する多くのルール([your-attribute])を持つCSSファイルです。 シャットダウン後、プロジェクトは復活し、イースターバニーのように実行されました。 しかし、堆積物は残りました。 問題の深さを理解するためのベンチマークが必要でした(もちろん、私の人生は空であり、仕事だけが何らかの形で楽しませることができますが、私たちは文化的な人々であり、そのような下品なことを想定しませんか?) 答えが欲しかった。 私は、このライブラリを聖なる審問の拷問装置の1つでなくなるように書き換える必要があることを理解したかったのです。
ベンチマーク
パフォーマンスを測定するために、 単純なPythonスクリプトが作成されました。 そのタスクは、異なる数のブロックとクラスおよび属性のCSSルールを使用して一連のhtmlファイルを作成し、JSコードを挿入して実行時間を決定することです。
HTMLファイル構造:
<!doctype html> <html> <head> <title>CSS Tag Selctor Test</title> </head> <body> <style> CSS goes here </style> <script type="text/javascript">var renderTime = Date.now();window.addEventListener("load", () => console.log(Date.now() - renderTime))</script> <div>0</div> <div>1</div> <div>2</div> ... <div>n</div> </body> </html>
各divにはクラス、
<div class="test-selector-0">0</div>
どちらかの属性
<div test-selector-0>0</div>
各CSSルールは、ブロックの背景色を設定します。 各ブロックは1つのルールのみに対応しています。 ルールの数がブロックの数より少ない場合、それらは最初から再び適用されます。 ロード時間(ミリ秒)は、ロードイベントによって決定され、コンソールに表示されます。
テスト用に、4GBのRAMと2つのコアを備えたWindows 10 Enterpriseで新しい仮想マシンが作成されました(より正確には、これは1つの物理コアですが、ハイパースレッディングのおかげで2つのスレッドが実行されます)。 ブラウザーMicrosoft Edge 38.14393.0.0、Google Chrome 60.0.3112.101、Mozilla Firefox 55.0.2が使用されました。 一度に1つのブラウザのみが開かれ、1つのタブのみが開かれました。 ベンチマーク結果に対するシステムプロセスの影響を回避するため、各ブラウザーで各テストを10回実行し、中央値を取得しました。 例外は、エッジのテスト「10,000ブロック/属性の10,000ルール」、「50,000ブロック/属性の10,000ルール」でした。 それぞれ5回と3回の測定のみが行われました。 5〜6分間ページのレンダリングを待つのが面倒でした。 将来的には、中央値のみで動作します。 完全な結果はここにあります 。
100個のCSSルールの結果
ブロック | クロム
(クラス) | Firefox
(クラス) | エッジ
(クラス) | クロム
(属性) | Firefox
(属性) | エッジ
(属性) |
---|---|---|---|---|---|---|
100 | 4 | 16.5 | 30 | 4 | 18 | 23.5 |
1000 | 16.5 | 95.5 | 44 | 19 | 125.5 | 139.5 |
10,000 | 437.5 | 653 | 382 | 452 | 585 | 1338.5 |
50,000 | 3489 | 2565 | 5176 | 3566.5 | 2865.5 | 7061 |
1000 CSSルールの結果
ブロック | クロム
(クラス) | Firefox
(クラス) | エッジ
(クラス) | クロム
(属性) | Firefox
(属性) | エッジ
(属性) |
---|---|---|---|---|---|---|
100 | 12.5 | 20.5 | 16.5 | 17.5 | 38.5 | 128 |
1000 | 40.5 | 115.5 | 127.5 | 96.5 | 198.5 | 647.5 |
10,000 | 479 | 618.5 | 974 | 960 | 1242 | 4578 |
50,000 | 3719.5 | 2877.5 | 5358.5 | 5936 | 6582.5 | 26597.5 |
10,000個のCSSルールの結果
ブロック | クロム
(クラス) | Firefox
(クラス) | エッジ
(クラス) | クロム
(属性) | Firefox
(属性) | エッジ
(属性) |
---|---|---|---|---|---|---|
100 | 99 | 33 | 24 | 156.5 | 134.5 | 1034.5 |
1000 | 149 | 85 | 77.5 | 618 | 8760 | 5185.5 |
10,000 | 655 | 625.5 | 788 | 5466 | 11020.5 | 46623 |
50,000 | 3681.5 | 3183.5 | 4743.5 | 36779 | 50663.5 | 326838 |
この調査の根本原因となったライブラリが元のアプリケーションに接続されていたが、単一のクラスが使用されていなかったという事実を考えると、別のテストを実施することが決定されました:CSSルールが実際にHTMLに適用される場合といいえ(つまり、CSSにありますが、誰も使用しません)。 これを行うために、元のベンチマークに--no_apply_cssオプションが追加されました。
10000 CSSルールの結果(括弧内に何も示されていない場合、HTMLでCSSルールが使用されました)
ブロック | クロム | Firefox | エッジ | クロム
(CSSは適用されません) | Firefox
(CSSは適用されません) | エッジ
(CSSは適用されません) |
---|---|---|---|---|---|---|
100 | 156.5 | 134.5 | 1034.5 | 177 | 84.5 | 1213.5 |
1000 | 618 | 8760 | 5185.5 | 689 | 562 | 6037 |
10,000 | 5466 | 11020.5 | 46623 | 6700 | 5156 | 76401 |
50,000 | 36779 | 50663.5 | 326838 | 38750 | 34351 | 431700 |
おわりに
ご覧のとおり、属性を使用すると、特定のCSSファイルサイズからすべてのブラウザーのパフォーマンスが低下します。 それにもかかわらず、エッジはここで際立っており、地球と呼ばれる私たちの青いボールで最速のブラウザとしての評判を恥じませんでした。 それをどうしますか? CSSを記述するために属性を使用しないでください。 また、接続するライブラリを非常に慎重に検討する価値があります。これらのライブラリには、属性に関するこのような不要なルールが多数含まれています。 そして、前回の実験で示したように、巨大なリストまたはテーブルを表示することにしたページの属性にルールを使用しなくても(「なぜ?」という質問はこの議論から除外されます)、パフォーマンスは依然として低下します。 何らかの理由で多数の属性セレクターの使用を避けられない場合は、それらを別のCSSファイルに収集し、緊急時にのみこのファイルをロードすることを検討する必要があります。 私自身、flex-attrをクラスに単純に転送し、作業が完了したら既存のプロジェクトをリファクタリングすることにしました。
他のコンテキストで実験データを確認する場合は、 Googleアカウントをコピーして、 必要に応じてデータを集計します。
UPD 08/08/2017:Microsoftにバグレポートを送信https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/13348719/