Closed8

Next.js / StoryBookでSVGを扱う

Hirotaka MiyagiHirotaka Miyagi

ひとまずNext.js側から。

SVGはこの画像を使う。
https://github.com/MH4GF/log.mh4gf.dev/blob/b7bebe5dc2a9c338b2138386fea905892b21cb45/src/assets/svg/external-link.svg

https://www.npmjs.com/package/@svgr/webpack に記載されているusage通りにwebpackのloaderを追加し、svgファイルをimportしてみる。

https://github.com/MH4GF/log.mh4gf.dev/pull/70/commits/2b147d56bad2908c71daa3f030e0b61651586a32
https://github.com/MH4GF/log.mh4gf.dev/pull/70/commits/8b51df8de118dc64ef5b8fea33331e18f35893e3

表示されますやん…!Vercelにデプロイした環境でも…!

Hirotaka MiyagiHirotaka Miyagi

続いて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
  },

https://github.com/MH4GF/log.mh4gf.dev/pull/70/commits/74112a2da26f8be4920f1fc990787574fc481333

しかしエラーになるな…?

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

https://github.com/MH4GF/log.mh4gf.dev/runs/6175094920?check_suite_focus=true

TypeError: this.getOptions is not a function

Hirotaka MiyagiHirotaka Miyagi

https://github.com/gregberge/svgr/issues/631
この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'
Hirotaka MiyagiHirotaka Miyagi

これは、探してみると以下のissueのワークアラウンドで解決できた。
https://github.com/storybookjs/storybook/issues/15336#issuecomment-906809203
main.jsに以下の一行を追加する
https://github.com/MH4GF/log.mh4gf.dev/blob/278a518ff43f395d44020ade27392d1c650772bf/.storybook/main.js#L43
webpack5のサポートはまだexperimentalなので仕方なさそうか…


これによりビルドは通るようになったが、コンポーネントの表示でエラーになっている
https://github.com/MH4GF/log.mh4gf.dev/runs/6291350907?check_suite_focus=true

Failed to execute 'createElement' on 'Document': The tag name provided ('static/media/arrow-right.981294d1.svg') is not a valid name.
Hirotaka MiyagiHirotaka Miyagi

このエラーはStoryBookがデフォルトで用意するwebpackの設定で、svgの拡張子の場合もfile-loaderでロードされてしまうのが原因。

https://github.com/storybookjs/storybook/issues/9070

それを打ち消すように設定すれば解決した。

  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にクローズされました