かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

Next.js SVG ファイルを React component として import したい!

create-react-app した React アプリでは何もしなくても SVG ファイルを import { ReactComponent as MySVGImage } from './svg/my-image.svg'; で読み込みコンポーネントとして扱うことができました。

Next.js でも同じことができると思ったのですが、create-next-app しただけの状態では SVG ファイルをそのまま import することができませんでした。(エラーになる)

create-next-app した Next アプリで SVG ファイルを React component として import できるようにする!

1. babel-plugin-inline-react-svg を導入する

$ npm -i D babel-plugin-inline-react-svg 

1-2. .babelrc にプラグインの設定をする

root に .babelrc ファイルを作成して inlne-react-svg を使えるようにする

.babelrc

{
  "presets": ["next/babel"],
  "plugins": ["inline-react-svg"]
}

これで import MySVGImage from './svg/my-image.svg'; のように SVG ファイルを React Component として読み込めるようになりました! (Named import ではないですが)

2. SVG の import にも path.alias が使いたい!

コンポーネントから SVG を読み込ませる時に ../../../../svg/my.svg のようにインポートするのはちょい辛いです。

Next で path.alias を使う

tsconfig.json に下記設定を加えると @/./src/ フォルダに、 ~/public/public フォルダに直接アクセス可能となります。

{
  "baseUrl": "src",
    "paths": {
      "@/*": ["./*"],
      "~/public/*": ["../*"]
    },
}

上記のNext.js 側で path.alias を指定していたので SVG でもそのまま @/svg/my.svg のように import できるものだと思っていたのですが、パスが解決できずエラーになってしまいました。

2-1. SVG ファイルにパスエイリアスを適応するには別途 babel-plugin-module-resolver で設定が必要

SVG は babel を通じて import できるようになっているので、パスの解決も babel での設定が必要なようです

$ npm i -D babel-plugin-module-resolver

2-2. .babelrc にエイリアスの設定を追加する

.babelrc

{
  "presets": ["next/babel"],
  "plugins": [
    "inline-react-svg",
+   [
+     "module-resolver",
+     {
+       "alias": {
+         "@": "./src/"
+       }
+     }
+   ]
  ]
}

"module-resolver" の設定で baseUrl も指定可能だったのですが、baseUrl: "./src" とすると tsconfig での設定とバッティングしてしまうようで SVG 以外の エイリアスを使ったインポートの箇所でエラーが出てしまいました。
上記の例のように baseUrl 指定なしで、alias に直接 .babelrc のある階層からのパスを指定してあげればバッティングすることなく同じパスエイリアスが使えるようになりました!

所感

Next.js でも create-react-app と同じ様に使えるんだと思っていたら別途設定が必要だったのですが、公式に例が合ったおかげでサクッと実現することができました。(named import にする方法は調べなかった) パスエイリアスの方は少しハマってしまいましたが、一度設定の作り方解ってしまえば次に活かせるのでヨシ!(๑•̀ㅂ•́)و✧
環境作り王に俺はなる…!!


[参考]

かげきしょうじょ!! 見てください