コード分割とスマート読み込み戦略を使用して Next.js アプリを高速化する方法。
学習内容
この記事では、さまざまな種類のコードについて説明します。 分割方法と使用方法 動的インポートを使用して Next.js アプリを高速化できます。
ルートベースとコンポーネント ベースのコード分割
デフォルトでは、Next.js は JavaScript をルートごとに別々のチャンクに分割します。 ユーザーがアプリケーションを読み込むと、Next.js は必要なコードのみを 初期ルートですユーザーがアプリケーション内を移動する際にチャンクをフェッチする ルートが他のルートにも関連付けられていることが わかりますルートベースのコード分割により、 一度に解析してコンパイルする必要がある多くのスクリプトが ページの読み込み時間を短縮できます
ルートベースでのコード分割はデフォルトとして適切ですが、 コンポーネント レベルでコード分割を行うこともできます。多数の それぞれ別のチャンクに分割することをおすすめします。 そうすれば、重要でない大きなコンポーネントや特定の環境でしかレンダリングされないコンポーネントが ユーザー操作(ボタンのクリックなど)を遅延読み込みできます。
Next.js は動的な import()
をサポートしています。
JavaScript モジュール(React コンポーネントを含む)をインポートできる
各インポートを個別のチャンクとして読み込むことができます。これにより、
リソースの読み込みを制御できるため、
必要なコードのみをユーザーがダウンロードできるようにし
できます。Next.js では、これらのコンポーネントはサーバー側でレンダリングされます。
(SSR)
できます。
動的インポートの実例
この投稿では、シンプルな構成のサンプルアプリについて、いくつかのバージョンを取り上げました。 1 つのボタンが配置されていますボタンをクリックすると、かわいい子犬が表示されます。として アプリケーションの各バージョンを確認すると、動的インポートがどのように機能するか、 静的トレーニングと インポート その操作方法について説明します
アプリの最初のバージョンでは、子犬は components/Puppy.js
にあります。宛先
ページに子犬が表示されると、アプリは Puppy
コンポーネントを
index.js
と静的 import ステートメント:
import Puppy from "../components/Puppy";
Next.js がアプリをバンドルする方法を確認するには、DevTools でネットワーク トレースを調べます。
サイトをプレビューするには、[アプリを表示] を押します。[ 全画面表示
。
Ctrl+Shift+J キー(Mac の場合は Command+Option+J キー)を押して DevTools を開きます。
[ネットワーク] タブをクリックします。
[キャッシュを無効にする] チェックボックスをオンにします。
ページを再読み込みする。
ページを読み込むと、Puppy.js
を含むすべての必要なコードが
次のコンポーネントは index.js
にバンドルされています。
![6 つの JavaScript ファイル(index.js、app.js、webpack.js、main.js、0.js、dll(ダイナミック リンク ライブラリ)ファイル)が表示された DevTools の [Network] タブ。](https://web.developers.google.cn/static/articles/code-splitting-with-dynamic-imports-in-nextjs/image/devtools-network-tab-show-c3449cc648185.png?authuser=6&hl=ja)
[ここをクリック] ボタンを押すと、子犬の JPEG のリクエストのみが が [Network] タブに追加されています。
![ボタンがクリックされた後の DevTools の [Network] タブ。同じ 6 つの JavaScript ファイルと 1 つの画像が表示されている。](https://web.developers.google.cn/static/articles/code-splitting-with-dynamic-imports-in-nextjs/image/devtools-network-tab-the-94b209c5e4e56.png?authuser=6&hl=ja)
この方法の欠点は、ユーザーがボタンをクリックしても、
Puppy
コンポーネントを読み込む必要があります。
index.js
。この小さな例では大したことではありませんが、現実世界では
大きなコンポーネントを読み込んでいるときに
できます。
次に、アプリの 2 番目のバージョンを見てみましょう。このバージョンでは、静的インポートが
動的インポートに置き換えられますNext.js には next/dynamic
が含まれているため、
Next では、任意のコンポーネントに動的インポートを使用できます。
import Puppy from "../components/Puppy";
import dynamic from "next/dynamic";
// ...
const Puppy = dynamic(import("../components/Puppy"));
最初の例の手順に沿ってネットワーク トレースを調べます。
アプリを初めて読み込むときは、index.js
のみがダウンロードされます。今度は
0.5 KB 縮小(37.9 KB から 37.4 KB に減少)しました。これは、
Puppy
コンポーネントのコードが含まれていません。
![同じ 6 つの JavaScript ファイルを表示している DevTools ネットワーク。ただし、index.js は 0.5 KB 小さくなりました。](https://web.developers.google.cn/static/articles/code-splitting-with-dynamic-imports-in-nextjs/image/devtools-network-showing-8cbd4309d29c5.png?authuser=6&hl=ja)
Puppy
コンポーネントは、独立したチャンク 1.js
に配置されました。これは、
ボタンを押したとき:
![ボタンがクリックされた後の DevTools の [Network] タブ。追加の 1.js ファイルと、ファイルリストの下部に追加された画像。](https://web.developers.google.cn/static/articles/code-splitting-with-dynamic-imports-in-nextjs/image/devtools-network-tab-the-e42cc1846b47f.png?authuser=6&hl=ja)
実際のアプリケーションでは、多くのコンポーネントが 大きくして遅延読み込みする 最初の JavaScript ペイロードを数百 KB 削減できます。
カスタムの読み込みインジケーターを使用した動的インポート
リソースを遅延読み込みする際は、読み込みインジケーターを
遅れが生じた場合に備えてNext.js では、
dynamic()
関数に次の引数を追加します。
const Puppy = dynamic(() => import("../components/Puppy"), {
loading: () => <p>Loading...</p>
});
読み込みインジケーターの動作を確認するには、 DevTools:
サイトをプレビューするには、[アプリを表示] を押します。[ 全画面表示
。
Ctrl+Shift+J キー(Mac の場合は Command+Option+J キー)を押して DevTools を開きます。
[ネットワーク] タブをクリックします。
[キャッシュを無効にする] チェックボックスをオンにします。
[スロットリング] プルダウン リストで [Fast 3G] を選択します。
[ここをクリック] ボタンを押します。
ボタンをクリックすると、コンポーネントとアプリの読み込みに時間がかかるようになりました。 [読み込み中...] というメッセージがメッセージが表示されます。
![テキストが表示されている暗い画面](https://web.developers.google.cn/static/articles/code-splitting-with-dynamic-imports-in-nextjs/image/a-dark-screen-the-text-914039a8f2589.png?authuser=6&hl=ja)
SSR を使用しない動的インポート
クライアント側でのみコンポーネントをレンダリングする必要がある場合(例: チャット
ウィジェット)を使用するには、ssr
オプションを false
に設定します。
const Puppy = dynamic(() => import("../components/Puppy"), {
ssr: false,
});
まとめ
動的インポートをサポートする Next.js では、コンポーネント レベルのコードが 分割することにより、JavaScript ペイロードを最小限に抑え、アプリケーションの 読み込み時間が短縮されますすべてのコンポーネントは、デフォルトでサーバー側でレンダリングされます。 無効にすることもできます。