vite-plugin-svgr プラグインがアップデートされ設定などが変わっていたので改めてメモ
環境
- vite-plugin-svgr
4.2.0 - Vite
4.4.9 - TypeScript
5.1.6
vite-plugin-svgr v3 → v4
結論は最下部にあります。お急ぎの方は途中スキップしてください!
Before
プラグインの設定
vite.config.ts
import svgr from 'vite-plugin-svgr'; export default { // ... plugins: [svgr()], }
TypeScript に SVG を React Component として解釈させるための型ファイルを作成
@/types/svg.d.ts
declare module '*.svg' { import React = require('react'); export const ReactComponent: React.FC<React.SVGProps<SVGSVGElement>>; }
cf. reactjs - Module '"*.svg"' has no exported member 'ReactComponent' - Stack Overflow
App.tsx
import { ReactComponent as Logo } from './logo.svg'; return App: FC = () => { return <div><Logo /></div>; };
After
svg は ReactComponent as を使わず .svg?react でインポートする
公式のドキュメントに import Logo from "./logo.svg?react"; のようにインポートするように書かれている
1. {ReactComponent as Component} を default import に修正する
App.tsx
import Logo from './logo.svg'; return App: FC = () => { return <div><Logo /></div>; };
この状態だとフロントで Failed to execute 'createElement' on 'Document': The tag name provided ('/src/logo.svg') is not a valid name. のようなエラーが出る
2. .svg?react で import するようにする
どうやら SVG は .svg?react の形でインポートしなければプラグインが動作しないようになっているっぽい
tsconfig.json を変更して .svg?react を許容するようにする
{ "compilerOptions": { }, "include": ["src", "**/*.svg?react"], }
App.tsx
- import Logo from './logo.svg'; + import Logo from './logo.svg?react'; return App: FC = () => { return <div><Logo /></div>; };
3. vite-env.d に <reference types="vite-plugin-svgr/client" /> を追加する
この状態だと import Logo from './logo.svg?react の箇所が Cannot find module '@/logo.svg?react' or its corresponding type declarations.ts (2307) という Type Error が発生してしまう。
公式ドキュメントにあるように vite-env.d に /// <reference types="vite-plugin-svgr/client" /> という一文を追加するとこのエラーは解消される
vite-env.d
/// <reference types="vite/client" /> /// <reference types="vite-plugin-svgr/client" />
これで vite-plugin-svgr v4 で SVG を React Component として扱えるようになりました!
.svg?react で import させるのがイケてない…
プラグインが .svg?react でのインポートを矯正しているがゆえに tsconfig を修正したり、SVG を使いたい時に都度 ?react を追加するのが面倒でイケてないので ?react 無しでプラグインが動作するようにしたい
プラグインの設定で ?react 無しにできた!
プラグインのコードを見ていると下記のようにプラグインの初期化部分で拡張子がオプションになっていました
export default function vitePluginSvgr({ svgrOptions, esbuildOptions, include = "**/*.svg?react", exclude, }: VitePluginSvgrOptions = {}): Plugin {
cf. vite-plugin-svgr/src/index.ts#L14-L19
vite.config.ts でプラグインを実行させる箇所で include オプションを使って ?react 無しの svg を対象にしてしまえば ?react 無しで動作させることができました
vite.config.ts
import svgr from 'vite-plugin-svgr';
export default {
// ...
- plugins: [svgr()],
+ plugins: [svgr({ include: "**/*.svg" })],
}
.svg?react を使用しないので tsconfig で *.svg?react を有効化する必要がありません
tsconfig.json
{
"compilerOptions": {
},
- "include": ["src", "**/*.svg?react"],
+ "include": ["src"],
}
同様に /// <reference types="vite-plugin-svgr/client" /> の設定も .svg?react という拡張子の型エラーに対応するものだったの不要
vite-env.d
/// <reference types="vite/client" /> - /// <reference types="vite-plugin-svgr/client" /> +
これで import Logo from './logo.svg' のような形で SVG を React Componentn として扱えるようになりました!
?react のオプション要らなくない?って思ってしまった…
結論 vite-plugin-svgr v4 はデフォルトでは .svg?react 拡張子を対象にしているが、オプションで .svg を対象に変更すると簡単!
vite.config.ts
import svgr from 'vite-plugin-svgr'; export default { // ... plugins: [svgr({ include: "**/*.svg" })], }
App.tsx
import Logo from './logo.svg'; return App: FC = () => { return <div><Logo /></div>; };
フロントエンド スナック感覚で仕様が変わるからアップデートでハマりがち…
おわり!
[参考]

