Suspense によるコンポーネントの dynamic import
この記事では、React 16.6 で追加された Suspense によるコンポーネントの dynamic import について紹介します。
(React 18 の Suspense の新機能についてはあえて触れませんが、続きの記事で解説する予定です。)
dynamic import とは
JavaScript には 静的インポート(static import) と 動的インポート(dynamic import) があります。
ES2019までのインポート方法である import 文 では、非同期にモジュールを読み込むことができませんでした。
import xxxxx from yyyyy
このように従来のインポートが 静的(static) であるのに対し、ES2020で追加された import()
式を使用することで、非同期にインポートができるようになりました。これが 動的インポート(dynamic import) です。
const xxxxx = await import(yyyyy)
dynamic import のメリットとして、webpack 等によるバンドルで生成される JavaScrript ファイルのサイズを削減することがよく上げられます。
サスペンスを使った React コンポーネントの dynamic import
ここからが本題です。React のコンポーネントを dynamic import する方法を紹介します。
React は Suspense
と lazy
を使うことで dynamic import ができます。
以下のように、lazy
で import()
式を返す関数を渡し、それを Suspense
の children
として渡します。
注意点として、Suspense
には fallback
を指定する必要があります。import()
を使った動的な読み込みが完了するまでの間、代わりに表示しておくものが fallback
です。
import { Suspense, lazy } from "react"
// lazy で import する
const SomeComponent = lazy(() => import("some_component")
// lazy で import したものを Suspense の children に
const Component = () => {
return (
<Suspense fallback={FallbackComponent}>
<SomeComponent />
</Suspense>
)
}
この Suspense を使って dynamic import すれば必ずパフォーマンスされるわけではありません。
例えば Suspense によってファイル分割を行ったとしても、そのコンポーネントをページ初期読み込み時に render される場合は、追加でサーバーへリクエストする回数が増え、読み込むファイルも増えてしまいます。
逆に、Suspense が有効な例として、ページの下の方に位置する重いコンポーネントがある場合に、スクロール後に dynamic import されるようにしておくことで、ページ初期読み込み時に読み込む JavaScript ファイルを削減し、ページ読み込み速度が改善されます。Qiita でも、記事ページの下にあるコメント一覧は、Suspense によってスクロール後に読み込まれるようになっています。
そして、React 18 の Suspense へ...
この記事を書いたきっかけは、Qiita社内での React新機能勉強会 です。そこで、React18 の Suspense の新機能の前に、React18以前の Suspense と lazy を使う方法を振り返りました。本記事はその際の資料を基に作成しています。
本記事では React 16.6 で追加された Suspense としての機能の紹介でしたが、React 18 では lazy
を使った dynamic import だけでなく、一般的な非同期処理と Suspense を組み合わせることができるようになったらしいので、社内の React 勉強会で出てきたら、続きの記事を書こうと思います!