
私はかなり長い間報告書に取り組んでおり、可能な限り物議を醸すようにした。 そして、すぐに矛盾から始めます。Webコンポーネントを使用できるという事実には根本的に同意しません。 質問はすでに約300 Kバイトで提起されていますが、Javascriptaページの300 Kバイトは容認できないほどたくさんあると確信しています。
今日は、フロントエンドへのかなり深い旅についてお話します。 この旅は、フロントエンドの
aviasales.ruが遅く、何かする必要があることを発見したときに始まりました。 この旅は1年半か2年前に始まりました。私が話すことは、私が学んだことを凝縮した物語です。
私の意見では、フロントエンドアプリケーションのパフォーマンスで最も重要なのはレンダリングです。 DOMでの作業は避けるべきものであることがわかっています。 DOM APIへの呼び出しが多いほど、アプリケーションの実行は遅くなります。

正確に何を話しますか? ゲームのルールについて。 レンダリングにはどのようなものがあり、Webアプリケーションの操作では、レンダリングのテンプレートライブラリのキーとなるパラメーター、テンプレートエンジンのタイプに注意する必要があります。
次に、巨人の骨に沿って少し歩きます。これらはAngularJSとReactJSです。なぜ私はそれらが好きではないのか、なぜ彼らは遅くなるのかを教えてみましょう。 上記のすべての知識に基づいて、他のテンプレートエンジンや、私たちが作成した作業で良い結果が得られたことをお伝えします。
おそらく視聴者の一部は、画面の下部にあるダイバーが何を意味するのか興味がありますか? 私たちの開発チームはタイにあり、私は個人的に飛び込みます。 このアナロジーは私の頭の中で生まれました。水中にいる場合は、動きを少なくすればするほど、酸素を節約すればするほど泳げます。 DOMでは、ほぼ同じことがわかります。DOMへの呼び出しが少ないほど、ユーザーがブレーキに遭遇する可能性は低くなります。

ゲームのルールから始めましょう。 ユーザーエクスペリエンスは、ページの初期化の速度に依存します。 私たちは皆、ページキャッシングに深く情熱を注いでいますが、キャッシングが機能しないとすぐに矛盾することを宣言する必要があります。 個人のサイトとの最初の接触が最も重要であるため、機能しません。 最初の読み込み中にサイトの速度が低下した場合、2回目はユーザーが戻ってこない可能性があります。 ページの初期読み込みは非常に重要です。
2番目に重要なことは、インターフェイスの応答性です。 ユーザーがボタンまたはチェックボックスをクリックしても、インターフェイスがすぐに応答しなかった場合、ユーザーはサイトを閉じて、インターフェイスが応答する別のサイトに移動できます。
次はリソースの消費です。 Webページでは、2つの主な指標が重要です:プロセッサの消費(多くの不要なアクションを行う場合、プロセッサを加熱し、インターフェイスでアニメーションを計算したり、単に何かを描画するのに十分な時間がない)、さらに多くを作成する場合不要なオブジェクトは、ガベージコレクターに負担をかけます。 ガベージコレクターで負荷を作成すると、定期的に呼び出され、アプリケーションの応答性が低下します。
そして最後ですが、これからも重要な点です。 ライブラリサイズ 単一ページのアプリケーションを使用している場合、200〜300、場合によっては400 KBのJavaScriptも余裕があります。 ただし、コンポーネントWebは、私たちが楽しそうに移動する方向に、ページが異なるWebコンポーネントから構築されていることを意味します。 さらに、これらのWebコンポーネントは多くの場合、さまざまな企業で生産され、独自のパッケージが付属しています。
多数のウィジェットが挿入されるページを想像してください:為替レート、天気、航空券、迫撃砲のダッシュ用ウィジェット...そしてこれらの各コンポーネントの重量は300 KBで、これはJSのみです。 したがって、5〜10 MBのページを簡単に取得できます。 すべてが順調になり、インターネットはどんどん高速になりますが、モバイルデバイスが登場し、低速ネットワークが登場しました。モスクワ市ではなく、エカテリンブルクのどこかでインターネットを使用すると、15 MBのWebサイトはまったく受け入れられない贅沢になります。 私の意見では、ライブラリのサイズが重要である理由です。
少し低めのいくつかのライブラリを比較し、ポリマーを比較しません。Webコンポーネントライブラリの200 KBが多すぎるという理由で比較しません。

それでは、会話のトピック、つまりテンプレートに移りましょう。
Webの開発に携わっている私たちは皆、文字列テンプレートエンジンにすでに慣れています。 文字列テンプレートエンジンは、作業の結果として文字列を返すテンプレートエンジンです。 後でHTMLのinnerHTMLを介して挿入する行。 これは素晴らしい、古くからの身近なメカニズムです。 ただし、いくつかの欠点があります。 主な欠点は、テンプレートを作成してinnerHTMLに貼り付けるたびに、前にあったDOM全体を破棄し、新しいDOMを挿入する必要があることです。
私の記憶では、DOMの操作は非常に遅いです。 30個の属性を持つ20個のタグをスローし、10個の属性を持つ同じ20個のタグを挿入した場合、これにはかなりの時間がかかります。 20ミリ秒は簡単です。 さらに、文字列テンプレートエンジンでは、単一の属性、単一のテキストノードなどをすばやく更新するためのアンカーを残すことはできません。
これらの準最適性を発見したので、これらの欠点を取り除く方法を探し始めました。それについて何ができるでしょうか? そして、ゴーグルが最初に提案したのは「DOM APIを使用する」ことでした。 このことは非常に単純ではありません。 しかし、彼女にはプラスがあります。

これはjsperfのスクリーンショットです。 innerHTMLおよびJS DOMからhtmlピースを挿入するストリングテンプレートエンジンのパフォーマンスを確認するベンチマーク。 ここでは、Androidのパフォーマンスが一番上にあり、JSDOM APIによりレンダリングを数回高速化できることがわかります。 ここで、約3回。 同時に、デスクトップブラウザではこのようなパフォーマンスの向上はありません。
約半年前、Googleはすべてのモバイル開発者に「moboheddon」を約束し始めました。 つまり、モバイルデバイスに対応していない、レスポンシブ、アダプティブなサイトはすべて、検索結果で悲観的になります。 これは、モバイルデバイスの準備ができていない場合、サイト上のGoogleからのトラフィックが大幅に減少することを意味します。
実際、このスライドは、DOM APIを使用すると、モバイルデバイスでのレンダリングを大幅に高速化できることを明確に示しています。 そして、これはAndroidだけに当てはまりません。 ご存知のように、最新のAndroidおよびiOSデバイスはすべて、ほぼ同じ最適化セットで同じWebKitエンジンを使用しています。つまり、DOM APIを介してページをレンダリングすると、すべてのiOSデバイスで同じパフォーマンスの向上が得られます。

ただし、DOM APIはやや面倒です。 ここに、DOM部分を作成できる5つの基本的な呼び出しをリストしました。 APIを介して直接DOMセクションを作成する場合、プログラムのコードに表示される形式でおおよそ引用しました。
15〜17文字に収まる1つの要素を作成すると、30〜50文字になります。DOMAPIを使用すると、5〜10行のコードを簡単に注ぐことができます。 プログラマの労働時間は貴重です。つまり、htmlを手動のDOMプログラミングに置き換えることはできません。

ここではテンプレートエンジンが必要です。 ご存知のように、文字列テンプレートエンジンは低速であり、DOMテンプレートエンジン、DOM APIを介して動作するテンプレートエンジンが必要ですが、通常のテンプレートエンジンでの動作に使用されるすべての利点を使用できます。
それでは、ネイティブのJSDOM APIを使用しないということは別として、DOMから何が得られるのでしょうか? これらを使用すると、DOMオブジェクトを変数に保存して、後ですばやく更新できます。 DOMテンプレートエンジンを使用すると、同じDOM部分を数回使用できます。
どういう意味ですか? Webストアページにアクセスするとします。 ユーザーは商品の1つのカテゴリを入力し、商品の1つのリストのデータが準備されたテンプレートに置き換えられます。 人が商品の別のカテゴリに入ると、他のデータが同じテンプレートに置き換えられます。 実際、DOMを再作成するのではなく、DOMの同じ部分を使用してデータを表示します。 これにより、プロセッサリソース、メモリ、および場合によってはプログラマの時間を大幅に節約できます。
私が必要とするツールはDOMテンプレートエンジンであるという考えに気付いた後、業界にすでに存在するもの、DOMを迅速かつ効率的に操作し、すばやくレンダリングするために使用できるものを確認しに行きましたか?
次に、私の意見では、巨人がどこでつまずいたかをお話しします。

私が話したい最初の巨人はAngularJSです。
私にはAngularJSが最初につまずいたようです。 これを使用した場合、おそらくすべてのテンプレートがDOMセクション(あまり良いスタイルではありません)または文字列としてクライアントに送信されることに気づいたでしょう。 ライブラリがロードされると、Angularは行またはDOMを実際のテンプレートにコンパイルするように強制されます。 これはクライアントで発生します。
興味深い状況を想像してください。 ユーザーはページにアクセスし、すべてのJSをロードします。これは、Angularアプリケーションの場合は非常に多く、100〜200〜300 Kバイトになります。 その後、各行解析テンプレートがコンパイルを開始します。 これはたった一つのことにつながります-Angularアプリケーションの初期ロードは、このコンパイルにより(ユーザーがサイトで作業する以外のことを行う間)0.5秒、1秒続くことがあります。 テンプレートをコンパイルするプロセスに2秒もかかったサイトに出会いました。 さらに、この問題は雪だるま式のように成長します。アプリケーション内のテンプレートが多いほど、単一ページのアプリケーションが複雑になるほど、テンプレートの初期コンパイルに費やす時間が長くなります。

次の問題はAngularにあります。 私たちは皆、AngularがGoogleの紳士によって最初のクールな両面バインディングフレームワークとして私たちに売られたことを覚えています。 さらに、この双方向バインディングは、いわゆるを通じて実装されます。 後でDOMに表示するためにデータ構造にハングアップする$ウォッチャー。 スライドには面白い写真がありますが、見ていません。 その中で唯一興味深いのは、この素晴らしいサイクルです。このサイクルでは、すべての$ウォッチがシステムにあるすべてのデータに使用されます。 さらに、もちろん、ドキュメントとすべてのチュートリアルで、$ watchersをフォローする必要があることをだれも教えません。 文字通り、次のことにつながります。 ある時点で、すばらしいアプリケーションは100ミリ秒ごとに遅くなり始めます。 アニメーションが遅くなり始め、メモリが流れ始めます。 多くの$ウォッチャーを許可することは不可能です。 多数のウォッチャーを作成するとすぐに、アプリケーションの速度が自然に低下し始めます。 ここでは、ブレーキを取り除くためだけに、微妙に自分自身を洗練し、何でもし、$ウォッチャーの数を減らし、Angularを使用した両面バインディングの適用を拒否し始めます。

さらに、Angularのアーキテクチャ上の欠陥は、AngularにはDOMを操作するための適切に記述された唯一の方法がないということです。 ディレクティブは実質的に独立しており、それぞれが適切と思われるDOMで動作します。 しかし、Angularディレクティブを調べると、一部のディレクティブを高速、一部を低速、一部のディレクティブを非常に低速としてマークできることがわかりました。
ng-repeatを使用している場合、100個の要素を詰め込み、$ウォッチャーも存在する場合、おそらくレンダリングに非常に長い時間がかかることがわかります。 問題は非常に広いため、Angularで作業する場合(以前のバージョンの出力は特にAngular上で構築されていた)、独自のng-repeatを作成する必要がありました。 これは従業員のアントン・プレシフツェフによって行われ、多くの会議でそれについて話しました。 さらに、私の意見では、最小化されたライブラリサイズの50 KBはまだ少し大きいです。 つまり 何を払っていますか? Angularコードを見ると、これらの50 Kバイトには独自のクラスシステムがありますが、Underscoreのバージョンは非常に低品質です。 そして、これらすべては、50 Kバイトのコードのフレームワーク内で完全に無料で入手できます。

以下。 私の意見では、はるかに優れたフレームワークはReactJSです。 インターネットがどのようにバブルしているのかを判断すると、すべての最初のプログラマーは、常にフロントエンドベンダーであるとは限らず、Angularを使用し、喜んでいました。 virtualDOMがDOMとの作業を高速化できるとは思いません。
virtualDOMが提供するものをご覧ください。 VirtualDOMは、ReactJSが実際のDOMを作成するソースです。 実際のDOMに加えて、どこからでも入手できない(virtualDOMを使用すると作成できる)のに加えて、ReactJSはvirtualDOMをメモリに保持します。これは冗長性と呼ばれます。
VirtualDOMは実際のDOMよりもわずかに小さく、おそらく5倍ですが、実際には、virtualDOMの2つのコピーをメモリに保持する必要があります。 つまり 実際のDOMを保持し、virtualDOMに実際のDOMの反映を保持します。さらに、virtualDOMでdivを作成するたびに、DOMの別のコピーを作成します。 1つのDOMがありましたが、現在は3つあります-よくできました! さらに、データを変更するたびに、virtualDOMの別のコピーを作成します。これは3番目のコピーですが、最初から作成します。
これにより、ガベージコレクターとプロセッサに深刻な負担がかかります。 さらに、私の意見では、ライブラリはまだ油っぽい-35 KB。 そして再び、彼らはクラスシステムを描画し、ローダッシュを描画することを決定しました。何らかの理由でオリジナルは適さず、これはすべて35 KBに詰められました。 さらに、恐ろしいパフォーマンスを提供すると思われる神話的なアルゴリズムが組み込まれたvirtualDOMがあります。
特にvirtualDOMとReactの次の問題は、ReactJSがデータのセマンティクスについて何も知らないことです。 この非常に単純な例を見てみましょう。

ここでは、2つのネストされた<div>があり、別の<i>タグが埋め込まれています。 virtualDOMを介して値を変更するには、React内のvirtualDOMアルゴリズムで3つのタグと1つのテキスト値を比較する必要があります。 データのセマンティクスがわかっていれば、テキスト値のみを比較するだけで十分です。テンプレートは、ある<div>内には常に別の<div>があり、次の<div>タグ<i>内にあると言っているからです... これは本当にオーバーヘッドです。
さらに、Reactでプログラミングした場合は、pure-render-mixinのようなものに精通しています。 その本質は、virtualDomでの作業をなくすことです。 漫画に近い非常に興味深い状況があります。 最初は、Googleの紳士がReactを数年間にわたって私たちに販売しました。これにより、virtualDOMを使用してDOMでの作業が非常に高速化されますが、DOMですばやく作業するには、virtualDOMを除外する必要があります よくやった、よくやった。
そして今、何か他のもの。 私は検索したかった-多分地球上に図書館があり、何かもっと良いことをした人々がいる。 特効薬の1つのライブラリを見つけようとしませんでしたが、Reactを高速化するため、または独自のライブラリを作成するために使用できるライブラリを覗き見したかったのです。 そして、ここに私が見つけたものがあります。

2つの興味深いライブラリを検討します。 これらの最初のものはRiotJSです。
私の意見では、RiotJSが正しいAngularJSであるのは、単にライブラリサイズが5 Kバイトだからです。 彼らは、AngularJSとまったく同じアイデアを取り入れましたが、lowdashを書き直さなかったのです。 彼はすでに書かれています。」 男たちは書き直さず、クラスシステムを発明せず、何もしませんでした。 5 kbライブラリを取得しました。 パフォーマンスはAngularJSよりも優れており、アイデアはまったく同じです。 さらに、RiotJSで使用されるテンプレートはデータセマンティクスを使用するため、パフォーマンスが大幅に向上します。 しかし、問題は残りました-テンプレートのコンパイルはまだクライアントで行われています。 それほど高速ではありませんが、はるかに優れています。

私の注目を集めた次のライブラリは、PaperclipJSでした。
PaperclipJSは、多くの非常に興味深い最適化を使用しています。 特に、cloneNodeを使用してテンプレートを作成し、パフォーマンスが大幅に向上することを示しますが、このソリューションを使用すると、PaperclipJSを開発者にとってより透明でわかりやすくすることができます。
しかし、このライブラリには2つの欠点もありました。それは非常に大きく、40 KBであり、Reactを超えています。 良いアイデアにもかかわらず、開発はかなり遅いです。 このライブラリは数年前から存在していましたが、まだベータ段階を離れていません。
これらのライブラリーや他のライブラリーと対話し、html5の第一人者を読んで、DOMでの作業を高速化できる以下の手法のリストを思いつくことができました。

最初のものはVirtualDOMです。 私はその利点を長い間探していましたが、たった1つしか見つかりませんでした。DOMの呼び出し回数を減らすことができるため、生産性が向上します。 ただし、私の意見では、DOMのコピーを作成するためのオーバーヘッドは依然として重要です。 Reactで使用されている秘密のベールがまだ残っている洗練された比較アルゴリズムは、約束されたほど高速ではありません。 それがどのように機能するかを理解するために、2日間を過ごします。 そして、私の意見では、ブログで説明されたこのすべての魔法はそこにはありません。 さらに、virtualDOMは、アルゴリズムがデータ構造について何も知らないという問題を抱えています。 データ構造については何もわかりませんが、すべてのラッパー、すべてのレイアウト要素は、それらの比較にvirtualDOMアルゴリズムが関与する必要があるため、パフォーマンスに悪影響を及ぼします。

非常に長い間知られている技術はcloneNodeの使用であり、PaperclipJSとDocumentFragmentのフレームワークで既に述べました。 これら2つの手法は、生産性を向上させるために使用されます。 私の知る限り、AngularJSまたはReactJSのいずれの手法も使用されていません。 ただし、jsperfを使用したベンチマークのスクリーンショットでは、これにより、DOMを使用した作業を少なくとも3倍高速化できることが明確に示されています。 かなり良い習慣です。使用することを強くお勧めします。

さらに、完全に表面にある次の手法は、Reactチュートリアルでも暗黙的に見つかりますが、事前にDOMセクションを作成することです。 どういう意味ですか? 人が電子ダミーのオンラインストアのページにアクセスするとします。 ティーポットの名前、購入するティーポットの会社の名前を紹介します。 この時点で、検索要求がサーバーに送信されます。 サーバープログラマーが高速かつ超高速の場合、20ミリ秒で応答を得ることができます。ユーザーはこれらの20ミリ秒の間、実質的に何もしません。 この時点で、サーバーから返されるデータのDOM構造を作成できます。 非常に簡単な練習。 なぜ広く使用されなかったのかはわかりません。 私はそれを使用し、それは非常にクールであることが判明しました。
合計、何が得られますか? サーバーに要求を送信し、サーバーからの応答を待機しながら、サーバーから送信されるデータのDOM構造を準備します。 サーバーからの回答が届くと、実際にはまだ解析する必要があります。 たいていの場合、それは単にJsonを受け入れることではなく、何らかの形でそれを適応させることです。 この時点でDOMの準備がすでに整っている場合、JSがデータを調整してDOMに挿入し、ページにデータを追加するために必要な2-3-4ミリ秒を費やすことができます。
これを使用することを強くお勧めします。フレームワークでは明示的にこのことはサポートされていませんが、サーバーにリクエストを送信するときに手で要素を作成できます。
, , , , .

temple. , , 2000 .
? JavaScript , .. , JavaScript . DOM . . , , gzip' – 700 . , , – DOM.
, .

. , .

, . , . forall if. . , React, , View . , , , . , Presenter ViewModel, , , .
, . , , , , , .
.

, update. DOM. DOM API. , , DOM remove. すべてが非常に簡単です。

DOM? , , . : « 10 ». , get, DOM , . つまり DOM .
? , 20 , , , 20, 200-300 , DOM , .. .
– , DOMContentLoaded.
DOMContentLoaded , , callback' , 100 . -. , DOM , , .

DOM. , , update React. React setState, . , , React, ( , , – DOM ), , React 50-60, .
, JavaScript, . DOM , . =2, .. , update, , . , value. =2, . update , . , – property =1, .

. , , , , , . , pool.release.

. . , , jsperf «» «». – , – React. C React , React, , , 5 , Angular . , ? 30 Chrom', 10-15 Firefox'. ? , , . create element, create text, node appendchild. . , . 35 JavaScript, React, – .

, – soft Update. Soft Update – , . , virtualDOM : «, , ». , virtualDOM pure-render-mixin. , . VirtualDOM .

, hard update. Hard Update – , , , . pure-render-mixin, . . hard update , virtualDOM.
VirtualDOM . React-, , virtualDOM . , virtualDOM, , , . React 20, 10.

, , . Aviasales – Facebook, -, … , – , . . . . React DOM delegate, AngularJS . , . . domdelegate Ftlabs. Ftlabs – IT- «Financial Times». , , , , 5 . , .

, , : aviasales.ru aviasales.ru. 10 , , 58 . , single page .
, , , 15 , 70 . , . , 70 single page application, . , 200.

, open source . , url . .
, , , . , , , , gulp grunt .
連絡先
»
BSKaplou»
bk@aviasales.ru— - FrontendConf . 2017 , 8 .
HighLoad++ " ". , , ( , ). .
: