📸
インラインSVGのReactコンポーネントを撲滅したらファイルサイズが94%削減された
はじめに
みなさんはReactでの開発する中で、どのようにSVGを扱っていますでしょうか?
CSSStyleの当てやすさから私たちのプロダクトではSVGをReactコンポーネント内で定義していましたが、パフォーマンスが良くないという問題にぶちあたりました。
今回はその問題への対処方法を共有したいと思います。
前提条件として弊社は以下の環境となっています。
next : 14.2.7
react : 18.3.1
react-dom : 18.3.1
typescript : 5.5.4
Node.js : 20.17.0
デプロイ環境 : Vercel
問題
トップページのサイズが217kbありFirstLoadJSは452kbもあり、読み込みに時間がかかっていました。
Lighthouseの評価もDOM sizeが1,747elementsとなっており異常な数でした。
同じSVGコンポーネントが同じページで連続して使用されてもキャッシュが効かず都度ロードされるため、ページの読み込みにも影響を与えていました。
解決方法
やることは2つです。
- SVGを.svgファイルとして切り出す
- Next.jsのImageコンポーネントを使ってSVGを読み出す
SVGを.svgファイルとして切り出す
以下のようなアイコンコンポーネントの場合は、svgタグの中身を外出しして.svgファイルにします。
export const ChevronRight = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="12"
height="13"
viewBox="0 0 12 13"
fill="none"
>
<path
d="M7.43878 6.96456L4.2568 3.78258C4.06154 3.58732 4.06154 3.27074 4.2568 3.07548C4.45206 2.88022 4.76864 2.88021 4.9639 3.07548L8.14589 6.25746C8.34115 6.45272 8.34115 6.7693 8.14589 6.96456C7.95062 7.15983 7.63404 7.15983 7.43878 6.96456Z"
fill="#777777"
/>
<path
d="M8.14596 6.96454L4.96398 10.1465C4.76872 10.3418 4.45214 10.3418 4.25687 10.1465C4.06161 9.95126 4.06161 9.63468 4.25687 9.43942L7.43885 6.25743C7.63412 6.06217 7.9507 6.06217 8.14596 6.25743C8.34122 6.4527 8.34122 6.76928 8.14596 6.96454Z"
fill="#777777"
/>
</svg>
)
Next.jsのImageコンポーネントを使ってSVGを読み出す
import Image from "next/image";
type Props = {
className?: string
}
export default function ChevronRight({ className }: Props) {
return (
<div className={className}>
<Image
src="/assets/icons/chevron-right.svg"
alt="chevron-right"
width={12}
height={13}
/>
</div>
)
}
おわりに
全てのSVGを外部リソース化したところSizeが94%も削減され、DOM sizeも59%削減されました!
参考になればと思います!
参考
Discussion