2023/10/06
Next.jsのDynamic Importを使ってパフォーマンス改善する
Next.jsのDynamic Importを使ってPageSpeed Insightsのパフォーマンススコアを60→94まで改善する事に成功しました!
デスクトップだと100点でした!
改善したページはこのサイトのコンポーネントページです。
実際に見てもらうとわかるんですが、iframeを使ってプレビュー画面を実装していたりcodemirrorでエディタ部分を実装していたりするので、普通のimportを使って実装すると最初に読み込むjsのサイズが大きくなってしまい、スコアがかなり落ちてしまうのが想像できるかと思います。
スクショ撮るの忘れちゃったんですが、改善前はスマホが60、PCが70ぐらいのパフォーマンススコアでした。
実際のコード
importからdynamic importに変更して、ローディング時の設定も行います。
Before
import Iframe from "./iframe";
import Editor from "./editor";
After
import dynamic from "next/dynamic";
import { Loading } from "@/components/loading";
const Iframe = dynamic(() => import("./iframe"), {
loading: () => (
<Loading />
),
});
const Editor = dynamic(() => import("./editor"), {
loading: () => (
<Loading />
),
});
ただ、これだけだと一番重いプレビューコンポーネント(iframe)は初期表示時に読み込みされてしまうので、editorの分しか早くなってません。
この時点でのスコアはこんな感じです。
なのでスタートボタンがクリックされるまではサムネイル画像を表示しておき、スタートボタンがクリックされてからプレビューコンポーネントを読み込むような形に変更しました。簡潔に書くと以下のような感じになります。
import dynamic from "next/dynamic";
import { Loading } from "@/components/loading";
const Iframe = dynamic(() => import("./iframe"), {
loading: () => (
<Loading />
),
});
const Editor = dynamic(() => import("./editor"), {
loading: () => (
<Loading />
),
});
export const Panel = ({ thumbnail, mode }) => {
const [clicked, setClicked] = useState(false);
return mode === "preview" ? (
!clicked ? (
<div className="relative h-[100%] w-[100%]">
<img
src={thumbnail}
className="absolute h-[100%] w-[100%] object-cover z-[1]"
alt="プレビュー画像"
/>
<div className="absolute z-[2] flex h-[100%] w-[100%] items-center justify-center">
<button onClick={() => setClicked(true)}>
クリックしてプレビューを開始する
</button>
</div>
</div>
) : (
<Iframe />
)
) : (
<Editor />
);
};
これでスマホが94点、PCでは100点の状態になりました!
おわりに
今回はクリックで読み込むように変更しましたが、画面の下のほうで読み込まれるコンポーネントだったらスクロールイベントを検知した時にコンポーネントを読み込むという風に設定する事もできますね。
とりあえず初期表示時に必要ではない大きいコンポーネントはなるべくdynamic importで読み込むという風に考えておくといいかもしれません。