Closed8
Next.js / StoryBookでSVGを扱う
要件
- リポジトリにSVGファイルを格納して、Reactコンポーネントから扱いたい
- Next.jsとStoryBook両方から扱いたい
パブリックリポジトリの個人開発のプロジェクトがあるとコードをそのまま載せられるから便利
軽く調べたら出てきたもの
一旦@svgr/webpackを試してみるのが良さそうか
ひとまずNext.js側から。
SVGはこの画像を使う。
https://www.npmjs.com/package/@svgr/webpack に記載されているusage通りにwebpackのloaderを追加し、svgファイルをimportしてみる。
表示されますやん…!Vercelにデプロイした環境でも…!
続いてStoryBookのmain.jsでもwebpackの設定を追加していく。
webpackFinal: async (config) => {
~~ 省略 ~~
// https://www.npmjs.com/package/@svgr/webpack
config.module.rules.push({
test: /\.svg$/,
issuer: {
and: [/\.(js|ts)x?$/],
},
use: ['@svgr/webpack'],
})
return config
},
しかしエラーになるな…?
ERR! => Failed to build the preview
ERR! ./src/assets/svg/external-link.svg
ERR! Module build failed (from ./node_modules/@svgr/webpack/dist/index.js):
ERR! TypeError: this.getOptions is not a function
ERR! at Object.svgrLoader (/home/runner/work/log.mh4gf.dev/log.mh4gf.dev/node_modules/@svgr/webpack/dist/index.js:83:24)
ERR! @ ./src/components/ArticleListItem/index.tsx 2:0-66 24:33-49
ERR! @ ./src/components/ArticleListItem/index.stories.tsx
ERR! @ ./src sync ^\.(?:(?:^|\/|(?:(?:(?!(?:^|\/)\.).)*?)\/)(?!\.)(?=.)[^/]*?\.stories\.(js|jsx|ts|tsx))$
ERR! @ ./generated-stories-entry.js
TypeError: this.getOptions is not a function
このissueを見るとwebpack5に上げればよいとのこと
yarn add --dev "@storybook/builder-webpack5@*" "@storybook/manager-webpack5@*
// main.js
module.exports = {
core: {
builder: 'webpack5',
},
...
これで実行してみるとこうなる
$ yarn storybook
yarn run v1.22.11
$ start-storybook -p 6006
info @storybook/react v6.4.22
info
info => Loading presets
info => Serving static files from ././public at /
info => Using PostCSS preset with postcss@8.4.13
info => Using default Webpack5 setup
<i> [webpack-dev-middleware] wait until bundle finished
9% setup compilation DocGenPlugininternal/modules/cjs/loader.js:905
throw err;
^
Error: Cannot find module 'webpack/lib/util/makeSerializable.js'
これは、探してみると以下のissueのワークアラウンドで解決できた。
main.jsに以下の一行を追加する webpack5のサポートはまだexperimentalなので仕方なさそうか…これによりビルドは通るようになったが、コンポーネントの表示でエラーになっている
Failed to execute 'createElement' on 'Document': The tag name provided ('static/media/arrow-right.981294d1.svg') is not a valid name.
このエラーはStoryBookがデフォルトで用意するwebpackの設定で、svgの拡張子の場合もfile-loaderでロードされてしまうのが原因。
それを打ち消すように設定すれば解決した。
webpackFinal: async (config) => {
~~ 省略 ~~
// @see https://github.com/storybookjs/storybook/issues/9070
const fileLoaderRule = config.module.rules.find((rule) => rule.test && rule.test.test('.svg'))
fileLoaderRule.exclude = /\.svg$/
return config
},
解決したため記事に整理し直した
このスクラップは2022/05/07にクローズされました