React Suspense と KaTeX (react-next-latex)

2023/12/21に公開

はじめに

Lighthouse のパフォーマンススコア向上のために、React プロジェクトのコード分割を始めた。
rollup-plugin-visualizer により、react-latex-next がバンドルファイルの多くを食っていることがわかった。

https://www.npmjs.com/package/rollup-plugin-visualizer

react-latex-next

KaTeX を React プロジェクトで用いるために、npm パッケージ react-latex-next を利用している。

https://www.npmjs.com/package/react-latex-next

Suspense によるコード分割

ビルドツール Vite による以下の箴言に従い、React.lazyimport() によるコード分割をすることにした。

(!) Some chunks are larger than 500 kBs after minification. Consider:
- Using dynamic import() to code-split the application
- Use build.rollupOptions.output.manualChunks to improve chunking: https://rollupjs.org/configuration-options/#output-manualchunks
- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.

https://legacy.reactjs.org/docs/code-splitting.html

関数コンポーネントのなかで import() により <Latex> コンポーネントを導入し、それをサスペンスで囲むようにする。

const QuotationCard = ({ quotation }: { quotation: Quotation }) => {
  const Latex = React.lazy(() => import("react-latex-next"));
  const quotationText = genQuotationText({
    text: quotation.text,
    page: quotation.page,
  })

  return (
    <blockquote>
       <Suspense
         fallback={quotationText}
       >
          <Latex>{quotationText}</Latex>
       </Suspense>
    </blockquote>
  );
};

すると、suspendedtrue のとき:

suspendedfalse のとき:

となる。

suspense を利用して react-next-latex の遅延読み込みを実装した。react-next-latex が読み込まれるまでは(最悪読み込まれなくても)\LaTeX 表記は平文で表示される。これが機能上の優れた点であろう。

おわりに

Quora のフロントエンドも \LaTeX 表記の遅延レンダリングを行っているが、おそらく本稿のような実装になっているのだと思う。

また、Lighthouse のパフォーマンススコアは 37 から 50 への上昇とまずまずの結果だった。

Discussion