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>; };
フロントエンド スナック感覚で仕様が変わるからアップデートでハマりがち…
おわり!
[参考]