React は、フロントエンド集中型のアプリケーションに広く使用されており、パフォーマンスとサイズを最適化する独自の方法を備えています。両方を改善すると、React パッケージのバンドル サイズにかなりの測定可能な影響が生じます。クライアントがレンダリングするアプリケーションに焦点を当てていることを考慮すると、バンドル サイズが小さいほど読み込み時間は速くなります。
サーバー側のレンダリングにより、読み込み時間がさらに短縮されます。サーバー側レンダリングでは、ユーザーが Web ページをリクエストすると、React コンポーネントがサーバー自体で HTML コードとしてレンダリングされます。次に、この事前レンダリングされたページがブラウザーに送信されるため、ユーザーは JS 読み込み時間のオーバーヘッドなしですぐにページを表示できるようになります。
しかし、それは全く別の話です。コードに微調整を加えてパッケージ バンドルのサイズを改善することに取り組み、クライアント側でレンダリングされるサイトを改善することに主に焦点を当てましょう。深く掘り下げてみましょう。
React コードの「バンドル」とは、すべてのインポートとコードをたどって、それを「バンドル」と呼ばれる 1 つのファイルに結合するプロセスです。 Webpack、Browserify などはすでにこれを行っています。
Webpack には「コード分割」と呼ばれる機能があり、単一のバンドルを小さなチャンクに分割し、チャンクの重複を排除し、それらを「オンデマンド」でインポートします。これは、アプリケーションのロード時間に大きな影響を与えます。
module.exports = { // Other webpack configuration options... optimization: { splitChunks: { chunks: 'all', // Options: 'initial', 'async', 'all' minSize: 10000, // Minimum size, in bytes, for a chunk to be generated maxSize: 0, // Maximum size, in bytes, for a chunk to be generated minChunks: 1, // Minimum number of chunks that must share a module before splitting maxAsyncRequests: 30, // Maximum number of parallel requests when on-demand loading maxInitialRequests: 30, // Maximum number of parallel requests at an entry point automaticNameDelimiter: '~', // Delimiter for generated names cacheGroups: { defaultVendors: { test: /[\/]node_modules[\/]/, priority: -10, reuseExistingChunk: true, }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true, }, }, }, }, };
React Suspense によるコンポーネントの遅延読み込み (React 18): これを動的インポートと組み合わせると、コンポーネントの読み込み時間に目に見える改善が見られます。
通常、親コンポーネント内に子コンポーネントをインポートするときは、静的にインポートします。実際にレンダリングする必要があるまでこのコンポーネントがインポートされないようにするには、動的インポートと React Suspense を組み合わせて使用します。 React Suspense を使用すると、オンデマンドでコンポーネントをロードできます。対応するコンポーネントが動的にインポートされてレンダリングされる間、フォールバック UI が表示されます。
import { lazy } from 'react'; // The lazy loaded Component has to be exported as default const BlogSection = lazy(() => import('./BlogSection.tsx')); export default function HomePage() { return ( <> <Suspense fallback={<Loading />}> <BlogSection /> </Suspense> </> ); } function Loading() { return <h2>Component is Loading...</h2>; }
これは、バンドルを作成する前に未使用のコードをすべて削除するために JavaScript バンドラーによって使用される手法です。 ES6 コードはツリーシェイク可能です。ただし、CommonJS に基づくコード (つまり、「require」を使用するコード) はツリーシェイクできません。
Webpack Bundle Analyzer は、インタラクティブなマップを使用して Webpack のサイズを視覚化するのに役立つプラグインです。
npm install --save-dev webpack-bundle-analyzer npm install -g source-map-explorer
次に、上記をプラグインとして追加するように Webpack を設定します。
plugins: [ new BundleAnalyzerPlugin(), new HtmlWebpackPlugin({ template: './public/index.html', // Path to your HTML template filename: 'index.html', // Output HTML file name inject: true, // Inject all assets into the body }), ];
スクリプトが Webpack を実行するように設定されていることを確認してください:
"build": "webpack --config webpack.config.js --mode production"
yarn build を実行して、バンドル サイズを効果的に視覚化するのに役立つ report.html を生成します。
次のようになります:
ブロッキング レンダリングとは何かを理解することから始めましょう。レンダリングのブロックとは、React がバックグラウンドでそれほど重要ではないタスクを実行していたために、メイン スレッド (UX 更新) がブロックされた場合です。これは React 16 まではそうでした。
React 18 には同時機能が導入されており、次のことが可能になります。
startTransition() フックを使用して React の更新を非緊急として管理し、React がユーザー入力やユーザーによるコンポーネントとの対話などの緊急の更新を以前の更新よりも優先できるようにします。
module.exports = { // Other webpack configuration options... optimization: { splitChunks: { chunks: 'all', // Options: 'initial', 'async', 'all' minSize: 10000, // Minimum size, in bytes, for a chunk to be generated maxSize: 0, // Maximum size, in bytes, for a chunk to be generated minChunks: 1, // Minimum number of chunks that must share a module before splitting maxAsyncRequests: 30, // Maximum number of parallel requests when on-demand loading maxInitialRequests: 30, // Maximum number of parallel requests at an entry point automaticNameDelimiter: '~', // Delimiter for generated names cacheGroups: { defaultVendors: { test: /[\/]node_modules[\/]/, priority: -10, reuseExistingChunk: true, }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true, }, }, }, }, };
この例では、入力値が変化すると、handleChange 関数が呼び出されます。 startTransition 関数は、リスト状態の更新を非緊急としてマークするために使用されます。これにより、React は値の状態への更新を優先し、リストが大きい場合でも入力の応答性を維持できるようになります。
useDeferredValue フックを使用して、UI のビジー状態がなくなるまで値 (通常は高価な計算) を延期します。
import { lazy } from 'react'; // The lazy loaded Component has to be exported as default const BlogSection = lazy(() => import('./BlogSection.tsx')); export default function HomePage() { return ( <> <Suspense fallback={<Loading />}> <BlogSection /> </Suspense> </> ); } function Loading() { return <h2>Component is Loading...</h2>; }
この例では、useDeferredValue フックを使用して、UI のビジー状態が少なくなるまで値の状態を延期します。これにより、入力の更新が処理されるまで大きなリストのレンダリングを延期することで、入力の応答性を維持することができます。
同時レンダリングの主な利点:
ロード中にアプリケーションが大量のリソースを取得することがわかっている場合は、そのリソースをプリロードすることをお勧めします。これらのリソースには、フォント、画像、スタイルシートなどがあります。
プリロードが有益なシナリオ:
module.exports = { // Other webpack configuration options... optimization: { splitChunks: { chunks: 'all', // Options: 'initial', 'async', 'all' minSize: 10000, // Minimum size, in bytes, for a chunk to be generated maxSize: 0, // Maximum size, in bytes, for a chunk to be generated minChunks: 1, // Minimum number of chunks that must share a module before splitting maxAsyncRequests: 30, // Maximum number of parallel requests when on-demand loading maxInitialRequests: 30, // Maximum number of parallel requests at an entry point automaticNameDelimiter: '~', // Delimiter for generated names cacheGroups: { defaultVendors: { test: /[\/]node_modules[\/]/, priority: -10, reuseExistingChunk: true, }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true, }, }, }, }, };
興味深い事実: プリロードを実装した後、Shopify、Financial Times、Treebo を含む多くのサイトで、インタラクティブまでの時間やユーザーが認識する遅延などのユーザー中心の指標が 1 秒改善されました。
このブログがお役に立てば幸いです!あなたのフィードバックは私にとって非常に貴重です ご意見やご提案を下のコメント欄に残してください。
さらに詳しい情報や最新情報が必要な場合は、LinkedIn でお気軽にご連絡ください。つながりを保ち、一緒に学び、成長し続けましょう!
以上がReactJS アプリケーションのパフォーマンスとサイズの迅速な最適化の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。