【Next.js】SVGRでSVGファイルをReactコンポーネントに変換する
イントロダクション
みなさんはNext.jsでSVGをどのように扱っていますか?
ReactならばReactComponent asで変換する方法を用いて簡単に描画ができますが、create-next-appで立ち上げたNext.jsだとそれが使えず、imgタグで描画している方もいらっしゃるのではないでしょうか。
そこで今回はNext.jsでもSVGのReactコンポーネントを使えるようにするため、SVGファイルからReactコンポーネントに変換する方法をご紹介いたします。
SVGファイルをReactコンポーネントに変換するメリット
まずはSVGファイルをReactコンポーネントに変換するメリットをご紹介します。
メリットはいくつかありますが、中でも大きいのは以下の3つかと思います。
- imgタグを使わないのでレンダリングの遅延によるレイアウト崩れが起こらない
- サイズや色の変更が容易になる
- TypeScriptによるサポートが受けられる
SVGファイルをReactコンポーネントに変換する方法
今回、SVGファイルをReactコンポーネントに変換するためにSVGRというライブラリを使用します。
GithubのStar数は10kを超えており、2023年時点でまだメンテナンスやリリースが続いているため、安心して導入しやすいかなと思います。
このSVGRのCLIを用いて、コマンド1つでReactコンポーネントに変換します。
SVGRの導入
まずは@svgr/cliをインストールします。
例ではpnpmを使用していますが、各自使っているパッケージマネージャに変換してください。
pnpm add --save-dev @svgr/cli
次に、svgrを実行するスクリプトを作成します。
#!/usr/bin/env bash
set -eu
pnpm svgr \
--typescript \
--memo \
--filename-case kebab \
--out-dir src/icons src/icons
スクリプトで指定しているオプションの意味は以下の通りです。
オプション | 意味 |
---|---|
--typescript |
.tsx で作成する |
--memo |
React.memo でラップする |
--filename-case kebab | ファイル名をケバブケースにする |
--out-dir src/icons | 出力先をsrc/icons にする |
その他のオプションが気になる方は以下を参照してください。
最後に、作成したスクリプトを実行するためにpackage.jsonのscriptsに追加します。
{
…
"scripts": {
"gen:icons": "./scripts/generate-icons.sh"
}
}
これでpnpm run gen:icon
を実行すれば無事src/icons
配下に置いたSVGファイルがReactコンポーネントに変換されるようになりました!
ただ、このままだとCSSでサイズを変更できなかったり、clipPathのidが一律でa
となってしまったりと使いづらい面が残っています。
そこで、設定ファイルを作成し、それらの問題を解消しましょう。
module.exports = {
svgoConfig: {
plugins: [
{
name: "preset-default",
params: {
overrides: {
removeViewBox: false,
cleanupIds: false,
},
},
},
],
},
};
removeViewBox: false
はviewBoxを残す設定で、これによってCSSによるサイズ変更が可能になります。cleanupIds: false
は未使用のIDの短縮を無効化しているため、clipPathのidが一律でa
になるのを防いでくれます。
応用:Reactコンポーネントのテンプレート編集
基本的な導入は以上なのですが、SVGRにはReactコンポーネントのテンプレートを編集する機能があり、一部の人には需要がありそうなので、簡単にご紹介します。
まずはテンプレートをいじる前に.svgrrc.js
でtemplateの指定をします。
module.exports = {
template: require("./src/icons/template.js")
…
}
後は./src/icons/template.js
にテンプレートを書いていくだけです。デフォルトのテンプレートは以下のようになっています。
const template = (variables, { tpl }) => {
return tpl`
${variables.imports};
${variables.interfaces};
const ${variables.componentName} = (${variables.props}) => (
${variables.jsx}
);
${variables.exports};
`
}
module.exports = template
このデフォルトテンプレートを元に、例としてファイルの最上部にコメントを追加した場合、以下のようになります。
const tips = `
// このファイルは自動生成されています。直接編集しないでください。
`
const template = (variables, { tpl }) => {
return tpl`
${tips}
${variables.imports};
${variables.interfaces};
const ${variables.componentName} = (${variables.props}) => (
${variables.jsx}
);
${variables.exports};
`
}
module.exports = template
詳しい解説は長くなりそうなので割愛しますが、以下の公式ドキュメントに詳細が記載されているので、気になる方はご覧になってください。
あとがき
以上、SVGRを用いてSVGファイルをReactコンポーネントに変換する方法でした。
SVGRは弊社のプロダクトでも採用しており、今でもワークしているライブラリです。導入と運用がとても簡単なので、迷ったらぜひ一度試してみてください。
Discussion