本記事ではコード分割(Code-Splitting)でフロントエンド最適とのことを説明させていただきます。
結論
Single Page Application(SPA)の仕組みとは、初めてWebAppにアクセスすると、重いJSファイルを読み込んでから、ユーザブラウザ自体でHTML生成したりDOMを作成したりする処理を行います。
メリット
即時反映 (初期時点以外)
画面遷移それともUI変更され場合は、API叩いて、(HTML,CSS,JSを含まない)最新なデータをUIに入れます。
デメリット
初期時点アクセスでは所要時間がかかります
TOPページにアクセスしますが、TOP以外のものを読み込んでからTOPページ表示します。
実践でCode-Splitting応用
- Navigationケースであり、ルートコンポーネントに重い各ページを遅延読み込み
- ページの内に一部重いUIがあって、読み込でいる時に一応「読み込み中のUI」表示
Code Splitting 利用しない
課題
- 重い
Base64
で送信時間がかかる -
RenderHeavyComponent
でUI生成時間がかかる
従って、お待ち時間がかかってユーザー体験が下がります
Code Splitting 利用
解決
- 軽いものを先に表示
- 重いものに対して一応「読み込み中」を表示して、段々表示
深く理解
Vue, AngluarとのフロントエンドライブラにもCode-Spilitingがありますが、本記事では下記のReactで深く説明します。
利用しない
模擬コード
import React from "react";
import ComponentA from "./ComponentA";
import ComponentB from "./ComponentB";
import ComponentC from "./ComponentC";
import Base64 from "./Base64";
import RenderHeavyComponent from "./RenderHeavyComponent";
function App() {
return (
<>
<ComponentA />
<ComponentB />
<ComponentC />
<Base64 />
<RenderHeavyComponent />
</>
);
}
export default App;
<Base64 />
と <RenderHeavyComponent />
は詳細が下の「その他」にあります。
ビルド段階
npm run build
結果
build/static/js/
配下にJSファイルが1つのみ出ました。サイズは4.63MBほどです。
読み込み段階
serve -s build
を行って、サーバー立ち上げます。
ブラウザー制限
- Disable Cached
- Network速度:Fast 4G
main.bbad9597.js
が4.6MBであり、ダウンロードとUI生成の時間が5秒ほどです。
→ ユーザが5秒を待たせます。
利用する
模擬コード
解説
-
const ComponentA = React.lazy(() => import("./ComponentA"));
とはReactの延長インポート -
<React.Suspense>
とはHOCです。こちらは重いコンポーネントを包み-
fallback
とは、読み込み中の時に指摘されるコンポーネントを表示
-
コード
import React from "react";
const ComponentA = React.lazy(() => import("./ComponentA"));
const ComponentB = React.lazy(() => import("./ComponentB"));
const ComponentC = React.lazy(() => import("./ComponentC"));
const RenderHeavyComponent = React.lazy(() => import("./RenderHeavyComponent"));
const Base64 = React.lazy(() => import("./Base64"));
function App() {
return (
<>
<ComponentA />
<ComponentB />
<ComponentC />
<React.Suspense
fallback={
<div>
<h1> LOADING Base64............</h1>
</div>
}
>
<Base64 />
</React.Suspense>
<React.Suspense
fallback={
<div>
<h1> LOADING.........</h1>
</div>
}
>
<RenderHeavyComponent />
</React.Suspense>
</>
);
}
export default App;
ビルド段階
npm run build
結果
6ファイルに分けています
読み込み段階
serve -s build
を行って、サーバー立ち上げます。
ブラウザー制限
- Disable Cached
- Network速度:Fast 4G
- 200msほぼ軽いUIを表示
-
RenderHeavyComponent
がUI生成中の時に、一応「 LOADING.........」を表示 - 重い
Base64Component
が5秒ほどダウンロードとUI生成を完了して表示。そして、処理中の時に、「LOADING Base64............」を一旦表示します。
実践でCode-Splitingを利用
おもいコンテンツを表示
ヘッダーとメニューとフーターが軽いコンポーネントで表示します。重いコンテンツに読み込みの時に、スプリンターとか一旦表示して、処理が完了してからコンテンツを表示します。そのためUIUXが改善
Navigation
Root.jsで以下のようにRouting設定します。
問題としては、/home
に入る時には、/users
そてとも/about
ページを表示しませんが、結構重くて、取得されます。したらがって、home
ページ表示速度に悪い影響を与えます。Code Splitting でこちら問題を解決できます。
その他、最新なNavigating LibraryにもCode Splittingが既に対応しています。
import React from "react";
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
export default function App() {
return (
<Router>
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/users">
<Users />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</Router>
);
}
その他
上記のコンポーネントがこちら
//Divを10000個表示
function RenderHeavyComponent() {
const [data] = useState(() => {
const arrays = [];
for (let index = 0; index < 10000; index++) {
arrays.push(index);
}
return arrays;
});
return (
<div styles={"background-color: green;"}>
Render Heavy Component
{data.map((dt, idx) => (
<div key={idx}>{dt}</div>
))}
</div>
);
}
//4MBほどの重いコンポネート作成するため、Base64 source ImgにRawエンコードを入れる
function Base64() {
return (
<div>
<h4>Base64</h4>
<img height={500} width={500} src={`
base 64 endcode here.. ~4MB
`}/>
</div>
)
}
参考
https://legacy.reactjs.org/docs/code-splitting.html
https://developer.mozilla.org/ja/docs/Glossary/Code_splitting
https://react.dev/reference/react/Suspense