@storybook/experimental-nextjs-vite で SVGR を使うには
結論
1. vite-plugin-svgr をインストール
2. .storybook/main.tsに以下のように記述
code:main.ts
import svgr from "vite-plugin-svgr";
const config: StorybookConfig = {
// ...省略...
viteFinal: (config) => {
// add svgr support
config.plugins = [
...config.plugins!,
svgr({
include: /\.svg$/,
}),
];
// HACK: To handle *.svg (without ?url) imports, we need to modify the existing plugin: "vite-plugin-storybook-nextjs-image"
// (set by @storybook/experimental-nextjs-vite)
// Because this plugin doesn't have a option to exclude certain file types
// TODO: Remove this workaround when the way to exclude certain file types is supported by the plugin
config.plugins = config.plugins!.flat().map((plugin) => {
if (
typeof plugin === "object" &&
plugin !== null &&
"name" in plugin &&
plugin.name === "vite-plugin-storybook-nextjs-image"
) {
return {
...plugin,
// The plugin handles *.svg by resolveId hook
resolveId(id, importer) {
// Skip .svg imports
if (id.endsWith(".svg")) {
return null;
}
// @ts-expect-error resolveId hook of vite-plugin-storybook-nextjs-image is a function
return plugin.resolveId(id, importer);
},
};
}
return plugin;
});
// ...省略...
return config;
},
};
export default config;
これは何?
前提知識
code:tsx
import SvgImage from "./image.svg"
<SvgImage />
これは、以下のことをするもの
1. デフォルトの *.svg と、その他画像ファイルをハンドルする loader から *.svg を除外する
2. ↑のloader の設定を複製して、*.svg?url でSVGファイルを読み込めるようにする
3. SVGR loader を追加する
なので、SVGR が示している Webpack の設定と同じことを、Viteの設定でする
Webpack の設定 rules には、loaderから特定のファイルの種類を除外する設定(exclude → Rule.exclude)があるが、Vite には同様のものが無い 無いよね…? もし ygkn.icon が知らないだけならお知らせください
なので、画像を読み込んでいるVite plugin("vite-plugin-storybook-nextjs-image")の処理(=ここではresolveIdフック)に横入りして(!)インポート文のクエリ(?...)が無い*.svg(=id.endsWith(".svg")) の場合は無視(=return null)して、SVGR のプラグインに処理を引き渡すようにする
つらい
†experimental† という感じがする
理想的には?
いちおう、TODO コメントにオプションができたらハック箇所を消すように書いてあげるとあとから見る人(∋自分)に親切
でもWebpackのSVGRもあとからごちゃごちゃしてるし、きついかな〜
Viteのpluginにexlcude設定ができるのでもおk