React.lazyを使った初回描画の高速化について

本稿はJCB Tech Blog Advent Calendar 2022の 12 月 23 日の記事です。

JCB デジタルソリューション開発部 アプリチームの山田です。

この記事では、私が担当している React 製の Web アプリの開発で初回描画の高速化検討をした内容についてご紹介したいと思います。

準備

今回は my-project-name という react アプリのプロジェクトを typescript で実装した例を紹介します。その準備として以下コマンドを実行します。

npx create-react-app my-project-name --template typescript
cd my-project-name
npm install react-router-dom
npm start

読み込みに時間がかかるコンポーネントを普通に import

Child1.tsx、Child2.tsx を src ディレクトリの直下に作成し、App.tsx を編集します。

Child1.tsx (軽量な処理を行うコンポーネント)
function Child1() {
  return <div>child1</div>;
}
export default Child1;
Child2.tsx (時間がかかる処理を行うコンポーネント)
const loop = () => {
  let i = 0;
  while (i < 10000000000) i++;
  console.log(i);
};

/**
 * ファイルの読み込み時に100億回ループさせる
 */
loop();

function Child2() {
  return <div>child2</div>;
}

export default Child2;
App.tsx (Child1.tsx と Child2.tsx を読み込むアプリ本体)
import { BrowserRouter, Routes, Route } from "react-router-dom";

import Child1 from "./Child1";
import Child2 from "./Child2";
import "./App.css";

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route index element={<Child1 />} />
        <Route path="Child2" element={<Child2 />} />
      </Routes>
    </BrowserRouter>
  );
}

export default App;

この状態でアプリを起動 ( npm start ) すると、以下のような結果になります。

通常のimport

初回描画に必要のない、Child2 の読み込みで loop 関数が実行されてしまい初回描画に 8 秒以上かかっています。 そこで React.lazy を利用し、動的に必要なタイミングでインポートすることで初回描画の高速化を試みます。

React.lazy を利用

以下のように App.tsx を編集

※ lazy を利用して動的に import する場合は <Suspense> で囲う必要があります。

App.tsx
import { Suspense, lazy } from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";

import Child1 from "./Child1";
// import Child2 from "./Child2";
import "./App.css";

/**
 * lazy を使い Child2 を import する
 */
const Child2 = lazy(() => import("./Child2"));

function App() {
  return (
    <Suspense fallback={<div>loading...</div>}>
      <BrowserRouter>
        <Routes>
          <Route index element={<Child1 />} />
          <Route path="Child2" element={<Child2 />} />
        </Routes>
      </BrowserRouter>
    </Suspense>
  );
}

export default App;

React.lazy を利用した import

初回描画で loop 関数が実行されなくなり高速化することができました。

今回の記事では、極端に1コンポーネントの読み込みに時間がかかるサンプルでしたが、実際には画面数の多い SPA 開発の際に役立つと思っております。しかし React.lazy を利用すると初回で読み込まない分、画面遷移時の読み込みは必要になりますのでご注意ください。

React.lazy については 公式サイト にも説明があるので良かったらご覧になってください。

おわりに

今回の記事では、初回描画の高速化について紹介させて頂きました。また機会があれば、初回描画以外のパフォーマンスや状態管理についてもご紹介したいと思います。

最後になりますが、JCB では我々と一緒に働きたいという人材を募集しています。 詳しい募集要項等については採用ページをご覧下さい。

©JCB Co., Ltd. 20︎21