Next.jsのアプリケーションでバンドルサイズを改善した話

環境

  • windows10
  • macOS Monterey 12.0.1
  • node 18.13.0
  • npm 8.19.3
  • React 18.2.0
  • Next.js 13.2.1
  • VsCode

この記事の内容

バンドルサイズを減少させることで、Next.jsアプリケーションのパフォーマンスを向上させようという話です。

具体的には、現状のバンドルサイズの確認ボトルネックの調査改善の手順となります

前提

next buildでビルド完了後、ページ単位でチャンクファイルが生成されチャンクファイルサイズの一覧が出力されます

右側に表示されているFirst Load JSは、ページにアクセスした際にダウンロードされるアセットのサイズなので、このサイズが大きいほどパフォーマンスが低下することになります。

また、First Load JSは色分けされ、緑、黄色、赤色で表示され、緑が最も高パフォーマンスということになっています

バンドルサイズの解析

ビルド時に表示されるチャンクのサイズだけでは調査が難しいので、別途専用のライブラリをインストールして、詳細を解析できるようにします。

@next/bundle-analyzer
Use `webpack-bundle-analyzer` in your Next.js project. Latest version: 13.4.4, last published: 6 days ago. Start using @next/bundle-analyzer in your project by ...
npm install @next/bundle-analyzer

next.config.mjsでimportし、環境変数がanalyze: trueの場合、バンドルアナライザーの処理が実行されるように指定します

参考:バンドルアナライザーのESM形式のサポート

Suppor ESM export for @next/bundle-analyzer · vercel/next.js · Discussion #31137
Describe the feature you'd like to request Since .mjs extension of next.config.mjs is supported the ESM export of @next/bundle-analyzer is necessary as well. Al...
import analyze from '@next/bundle-analyzer'


const withBundleAnalyzer = analyze({
  enabled: process.env.ANALYZE === 'true',
  defaultSizes: 'gzip',
})


/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true
}


export default withBundleAnalyzer(nextConfig)

.env.analyze

ANALYZE=true

npm scripsに実行用コマンドを登録

{
  "scripts": {
   .. 
    "analyze": "env-cmd -f .env.analyze next build"
  },

実行します

npm run analyze

実行後、以下3種類のhtmlが生成され、アクティブなブラウザに自動で新規タブに表示されます

  • .next\analyze\client.html
  • .next\analyze\edge.html
  • .next\analyze\nodejs.html

このうち、client.htmlはブラウザ側で使用されるJs、Cssのサイズが表示されており、その面積が大きいほどバンドルサイズ肥大化の原因になっている可能性が高いです。

特に、このlottie.js(react-lottie)はアニメーション用のライブラリであり、ほかのライブラリと比べバンドルサイズが大きいことが見て取れます。

いずれかのバンドルの上にマウスを置くだけで、その統計が表示されます。各バンドルの統計サイズ、解析済みサイズ、Gzip 圧縮サイズ、およびバンドルのファイルパスを確認できます。

サイズの種類

  • Stat size
    アプリを実行するためにブラウザがダウンロードして実行する必要があるJavaScriptのサイズ
  • Parsed size
    JavaScript実行後に Web ブラウザーで占有されるメモリの量
  • Gzipped size
    アプリを実行するためにブラウザがダウンロードして実行する必要があるJavaScript(Gzipアルゴリズムを使用して圧縮済み)

エディター上から確認すると、ライブラリ自体のサイズもかなり大きいことがわかります。

バンドルサイズの改善

まず、同じような問題に直面しているケースを探しその解決方法を探ります。探したところ、react-lottieの軽量版である、react-lottie-liteというライブラリがあることを知りました。

react-lottie-light
lottie animation view for React. Latest version: 1.2.5, last published: 3 years ago. Start using react-lottie-light in your project by running `npm i react-lott...

ただ、このライブラリは現在メンテナンスされていないようで、Reactのversionも15で止まっていました。

GitHub - chenqingspring/react-lottie: Render After Effects animations on React based on lottie-web
Render After Effects animations on React based on lottie-web - GitHub - chenqingspring/react-lottie: Render After Effects animations on React based on lottie-we...

そのため、react用のlottieライブラリの使用を断念し、lottie-web-light(lottie-webの軽量版)を使いつつ、reactの部分はオリジナルで実装するという方法を採用しました。

lottie-web-light
After Effects plugin for exporting animations to SVG + JavaScript or canvas + JavaScript. Latest version: 1.1.0, last published: 3 years ago. Start using lottie...
This library is no longer maintained. Making your own simple wrapper isn't difficult... · Issue #139 · chenqingspring/react-lottie
If you need something complex, then react-lottie-player looks good. Otherwise the code below is all you need to display a lottie animation on your page. There i...

※lottie-web-lightは軽量版なので、軽量版では実現できない複雑な処理が必要な要件がある場合は別の解決法を検討する必要があります。

改善結果

Stat sizeが約600kb→200kbまで減少しました。

Before

After

その他のヒント

未使用のライブラリが残ったままになっていることも、アプリケーション全体のサイズが肥大化する原因の一つです。

以下のコマンドを実行することで、未使用のライブラリをチェックすることが可能です。

※ただし、検知された結果は必ずしも正確ではないので、それらを 1 つずつアンインストールし、アプリを再実行して、期待どおりにビルドされ動作することを確認することをお勧めします。

npx depcheck
タイトルとURLをコピーしました