反応とコード分割

私は、Yandexが少し中断された2008年に、かなり前にコード分割に遭遇しました。サイトに同期接続されたYandex.Directスクリプトは、単にこのサイトを殺しました。 一般に、「スクリプト」が正しい順序で接続する10個のファイルである場合、当時は正常でしたが、それでも(遅延して)正常に機能します。

その後、カードを積極的に使用し始めましたが、それらはまだ外部スクリプトとして、もちろん遅延ロードとして接続されています。 次に、Yandex.Mapsチームのメンバーとして、 ymodulesを積極的に使用してクライアントでツリーシェーキングを使用しました。これにより、完璧なコード分割が実現しました。







そして、 webpack



React



に行き、 webpack



を新しい門の雄羊のように見た、おびえた馬鹿の国に行きました。







コード分​​割はすごい機能ではなく、必須です。 それでも、 SSR



は干渉しません...













小さな紹介



最近では、バンドルが毎日大きくなると、コードの分割がこれまで以上に重要になります。 当初、人々はアプリケーションの各ページに個別のエントリポイントを作成するだけでこの状況から抜け出しました。これは一般的には良いことですが、SPAでは機能しません。

次に、 require.ensure



関数が登場しました。 require.ensure



、今日dynamic import



(単にインポート)として知られています。この関数を使用して、モジュールを簡単に要求できます。







Reactのこのケースに関する最初のライブラリはreact- loadableでしたが、その周囲の誇大広告はまだ私にはあまり明確ではなく、すでに死んでいます(著者を喜ばせるのをやめました)。







さて、多かれ少なかれ「公式」な選択はReact.lazy



React.lazy



-components (ちょうど@loadable



)であり、それらの間の選択は明白です:









特に、loadableはライブラリをロードするための美しいラッパー(loadable.lib、react renderPropにmoment.jsを取り込むことができます)をサポートし、サーバー側のwebpackがプリフェッチ用の使用済みスクリプト、スタイル、およびリソースのリストを収集するのを支援します(webpack自体は実際には知りません)。 一般的に、 公式ドキュメントをお読みください。







SSR



一般に、問題はすべてSSRにあります。 CSR(クライアントサイドレンダー)の場合、React.lazyまたは10行の小さなスクリプトのいずれかが適合します-これは間違いなく十分であり、大きな外部ライブラリを接続することは意味がありません。 しかし、サーバー上ではこれでは十分ではありません。 また、SSRが本当に必要ない場合は、読み進めることができません。 長く難しい解決が必要な問題はありません。







SSRは苦痛です。 私は(ある意味では)ロード可能コンポーネントのメンテナーの1人であり、さまざまな場所からいくつのバグが出るのかというのは恐ろしいことです。 そして、アップデートのたびにwebpackはさらに飛ぶようになります。







SSR + CSS



SSRの問題のさらに大きな原因はCSSです。

Styled-componentsを使用している場合(それほど害はありません)、 transform-stream



が付属しており、最終的なコードに必要なものが追加されます。 主なものは、どこにでもSCの1つのバージョンがあるはずです、そうでなければフォーカスは機能しません-SCの1つのバージョンはそれ自体について他に何も伝えることができず、SCは増殖するのが大好きです(バンドルを確認してください)。 正直に言うと、フォーカスが通常失敗するのは、まさにこの制限のためです。







Cの感情はより単純です-それらのstyled



アダプターは、コンポーネント自体の前に<style>



単に吐き出し、問題は解決します。 シンプルで安くて陽気な。 原則として、非常にモバイルフレンドリーであり、非常に最初のビューを大幅に最適化します。 しかし、2番目は少し損なわれます。 そして個人的に、私の良心は私がそのようなスタイルをインライン化することを許可していません。







通常のCSS(さまざまなマジックを備えたさまざまなCSS-in-JSライブラリから取得したものを含む)を使用すると、さらにシンプルになります。それらに関する情報はwebpack列にあり、どのCSSを接続する必要があるかが「わかっています」。







接続順序



ここで犬は自分自身を埋めました。 いつ接続する必要がありますか?

SSRフレンドリーコード分割の意味は、 ReactDOM.hydrate



を呼び出す前に、サーバーの応答に既に存在するすべての「コンポーネント」をダウンロードする必要があるが、クライアントに現在ロードされているスクリプトには余裕がないことです。







したがって、すべてのライブラリは、すべてのすべてをロードする必要があるときに呼び出される特定のコールバックを提供し、 を起動できます。 これは、SSRコード分割ライブラリの作業の意味です。







JSはいつでも読み込むことができ、通常、そのリストはHTMLの最後に追加されますが、FOUCがないようにCSSを先頭に追加する必要があります。

すべてのライブラリは古いrenderToString



に対してこれを行うことができ、すべてのライブラリはrenderToString



に対してこれを行うことができません

JS(これは発生しません)またはSC / Emotion(それ自体が追加されます)のみを持っているかどうかは関係ありません。 しかし-もしあなたが「ちょうどCSS」を持っているなら-それだけです。 それらが最後になるか、 renderToString



または他のバッファリングを使用する必要があります。これは、TTFB(最初のバイトまでの時間)遅延を提供し、このSSRの一般的な意味をわずかに減らします。







そしてもちろん-これはすべてwebpackに関連付けられており、それ以外の方法ではありません。 したがって、ロード可能コンポーネントの作成者であるGregに敬意を払って-他のオプションを検討することを提案します。







次は3つのパートからなるアジェンダです。その主なアイデアは、殺されず、バンドラーに依存しないことを行うことです。


1. React-Imported-Component



React-Imported-Componentは悪い「ローダー」ではなく、多かれ少なかれ標準的なインターフェイスを持ち、ロード可能なコンポーネントに非常に似ており、移動するすべてのものをSSRできます。







アイデアはとてもシンプルです。









stats.json



stats.json



、webpack最適化(連結、または共通コード)に適応stats.json



必要はありません-配列のキーにある1つのインポートの「ラベル」を一致させて、再度インポートするだけです。 特定のバンドラーの一部として実行される方法、実際にダウンロードされるファイルの数、およびどこからでも問題ではない。







マイナス-「使用済み」チャンクのロードの開始は、マッピングを保存するメインバンドルのロード後に発生します。これは、この情報をHTMLに直接追加するロード可能コンポーネントの場合よりも少し「後」です。







はい、CCSでは、単語からはまったく機能しません。







2.使用済みスタイル



ただし、 used-styleはCSSでのみ機能しますが、react-imported-componentsとほぼ同じ方法で機能します。









TTBTの遅延はありません。バンドラーとは関係ありません-おとぎ話です。 スタイルがよく書かれていれば、時計のように機能します。







React-import-component + used-styles + parcel workingの例。







最も明らかなボーナスではありません-サーバーでは、両方のライブラリは、起動時に「エクスプレスサーバーが最初のクライアントを受信できるまで」「必要なすべて」を行い、サーバーとテストの両方で完全に同期されます。


3. react-prerendered-component



そして、ライブラリはトップ3を閉じます。これは「部分的な水分補給」を行い 、すぐに疑問に思うほどの祖父のやり方でそれを行います。 彼女は本当に「ディーバ」を追加します。









 const AsyncLoadedComponent = loadable(() => import('./deferredComponent')); const AsyncLoadedComponent = imported(() => import('./deferredComponent')); <PrerenderedComponent live={AsyncLoadedComponent.preload()} // when Promise got resolve - component will go "live" > <AsyncLoadedComponent /> // meanwhile you will see "preexisting" content </PrerenderedComponent>
      
      





このフォーカスは、プリロードpromiseから返されないため、loadable-componentsでは機能しません 。 これは、「コンテンツ」を持っているが「実際の」SSRを通過していない、 react-snap (および他の「レンダリング」)のようなライブラリにとって特に重要です。













コードの観点から見ると、これは10行に加えて、コードのロードと実行のランダムな順序を考慮して、 安定したSSR-CSR UIDを取得するためのもう少しの行です。







ボーナス:









原則として、状態の複製の問題を解決するためのライブラリを作成する主なアイデアは、シリアル化とシリアル化解除です(SSRに関する記事の写真)。 キャッシングは後で到着しました。







合計



合計で、SSRとコード分割の見方を変えることができる3つのアプローチがあります。 最初はJSコード分割で動作し、壊れません。 2番目はCSSコード分割で機能し、壊れません。 3番目の方法はHTMLレベルで機能し、一部のプロセスを簡素化および高速化します。また、破損しません。







ライブラリへのリンク:









記事(英語)










All Articles