blog

見落としがちなパフォーマンス最適化手法、サスペンス

サスペンス技術は当初、非同期コンポーネントをロードするために設計されましたが、次第にすべての非同期プロセスに適用されるようになりました。その中でも非同期リクエストはSusppenseの最も重要な利用シ...

Jul 13, 2020 · 4 min. read
シェア

はじめに

Suspense テクニックは当初、非同期コンポーネントをロードするために設計されましたが、 徐々に全ての非同期プロセスに適用されるようになりました。その中でも非同期リクエストはSusppenseが使われる最も重要なシナリオです。近い将来、Susppenseベースの開発パターンが主流になると同時に、ユーザーエクスペリエンスもSusppenseを使うことで最適化されるでしょう。



Suspenseの使い方は

Vueの使い方は

codesandbox.io/s/bold-cdn-...

Reactの使い方は

codesandbox.io/s/kind-swar...



Suspense

一般的な技術として、RespenseはReactとVueで基本的に同じように実装されています。

通信手段:Susppenseとその内部に組み込まれたコンポーネント間の通信、つまりSusppenseがコンポーネントの非同期状態を取得する方法。

レンダリングとは:Susppenseがその中に組み込まれたコンポーネントのレンダリングを制御する方法です。

Susppenseがコンポーネントの非同期状態を取得する方法

表面的には、VueもReactもSuspenseにプロミス関連のプロップを渡していないように見えます。固まった考え方では、propsがコンポーネントへの唯一のエントリポイントであると仮定するのは簡単です。

実際、サスペンスはフレームワークの組み込みコンポーネントとして、ランタイムに存在するあらゆる変数を取得する「完全な自由」を持っています。

  • Vueの場合、セットアップでpromiseを "return "すると、Vueはそのpromiseを取得し、自動的に一番近いSuspenseに渡します。

  • Reactの場合、レンダリングでプロミスが "throw "されると、Reactはそのプロミスをキャプチャして、自動的に一番近いSusppenseに渡すことができます。

このようにして、サスペンスはコンポーネントの非同期状態を取得します。

Susppenseに埋め込まれたコンポーネントのレンダリングを制御する方法

サスペンスは常にコンポーネントを隠しコンテナにプリレンダリングし、その後、関連するプロミスの状態に基づいて選択を行います:

  1. プロミスがペンディング状態の場合、フォールバックコンポーネントは実際のdomコンテナにレンダリングされます。

  2. プロミスがresolve状態に達した場合、プリレンダリングされたコンポーネントを実際のdomコンテナに直接移動し、フォールバックコンポーネントをクリアします。

  3. もしプロミスがrejectの状態になったら、フレームワークはrejectエラーを直接投げます。

フェーズ1 ユーザー・エクスペリエンスの最適化

コンポーネントで非同期データをロードすることは、ビジネスシナリオで最も一般的な要件です。 コンポーネントの状態は、非同期データの状態に応じて変化します。

異なるステートに対応するコンポーネントのコンテンツをレンダリングするために、従来のv-if/v-elseの形式、またはjsxの3項式を使用すると、実際にパフォーマンス上の問題が発生する可能性があります:

// template
<Loading v-if="loading">loading...</Loading>
<Content v-else>実際のコンテンツ</Content>
// jsx
(
	loading ? <Loading>loading</Loading> : <Content>実際のコンテンツ</Content>
)

2つの異なる要素のレンダリングを切り替える場合、どちらもコンポーネントの破壊と再構築を伴います。サスペンスでは、実要素とフォールバックの両方が同時に存在します。 フォールバックが現れても実要素は破壊されず、フォールバックが消えても再構築されません。

このようにして、ページのレンダリングパフォーマンスが大幅に改善されるため、ユーザーエクスペリエンスは最初の段階で最適化されます。



フェーズ2 ユーザー・エクスペリエンスの最適化

レンダリングのパフォーマンスは大幅に改善されました。では、他に何を最適化できるのでしょうか?Reactの並行処理パターンは、ローディング状態をキルオフするという新しいアイデアをもたらします。

React Concurrency PatternはReact Fiberアーキテクチャの応用で、コンポーネントツリーの更新はコンポーネント単位で非同期化され、メインスレッドをブロックしないようにコンポーネントの更新を中断することができます。

詳しくはreactjs.org/docs/concur...

実際の環境では、ユーザーの端末性能やネットワーク速度が異なり、性能が良くてネットワーク速度が速い人もいれば、性能が悪くてネットワーク速度が遅い人もいて、このような状況になります:

高い

低い

デバイスのコンディションはすでにとても良く、ミリ秒単位でデータをロードしていますが、それでもロード状態を点滅させています

低い

高い

デバイスの状態が悪く、セカンドレベルでデータをロードする場合、ロード状態があると快適です。

上記の問題は、Reactの同時実行パターンと組み合わせてSusppenseを使用することで解決できます:

codesandbox.io/s/elated-ca...

  1. 更新をクリックすると、リストが更新されます

  2. リストを更新するインターフェースには、0~1秒の間のランダムな時間がかかります。

  3. インターフェイスが0.5秒以内に戻った場合、ローディングステータスは表示されません。

  4. インターフェイスが0.5秒以外の時間を返した場合、ロードステータスが表示されます。



FAQ

待ってください、Reactの並行処理パターンを使わなくても、第2段階のUX最適化を実現できます。

タイマーを追加して、一定時間経過後にのみローディングが表示されるようにするだけです。

Vue UXはReactより劣っていますか?

VueはSusppenseのパフォーマンス最適化に貢献することはできませんが、Vueは別の方向からレンダリングパフォーマンスの大幅な向上をもたらします:vnodeを事前に分析し、タイプに応じて適切なpatchFlagを与え、フラグに応じて最も効率的な更新方法を取ります。





Read next

[ISV]callBackUrl

saasスイートの作成では、それはあなたが記入する必要があることに注意することが重要です、このURLを呼び出すと、バックグラウンドプロセスが正常であることを確認するために使用される特定の情報の戻り値を受信します。だから、スイートの作成では、最初にバックグラウンドアプリケーションを実行する必要があります。

Jul 13, 2020 · 1 min read