[@svgr/webpack] Next.js / Storybook でSVGをコンポーネントとして扱う

17701 ワード

やりたいこと

  • リポジトリにSVGファイルを格納して、Reactコンポーネントから扱いたい
  • Next.jsとStorybook両方で表示したい

記事要約

  • @svgr/webpackを利用し、webpackの設定を書いて解決する
  • Next.jsで表示するのは簡単だが、Storybookでは多くの罠があった

前提情報

Next.jsでの表示

まず@svgr/webpackを追加します。

yarn add -D @svgr/webpack

続いて next.config.js にwebpackの設定を加筆します。

// next.config.js

module.exports = {
  ~~~ 省略 ~~~
  webpack: (config) => {
    config.module.rules.push({
      test: /\.svg$/,
      use: ['@svgr/webpack'],
    })
    return config
  },
}

SVGファイルを格納し、適当なコンポーネントでimportし、JSXに加筆します。

import ExternalLinkIcon from '~/src/assets/svg/external-link.svg'

const App = () => (
  <div>
    <ExternalLinkIcon />
  </div>
)

これだけでNext.jsでSVGの表示ができるようになります。

Storybookでの表示

./storybook/main.js にもwebpackの設定を加筆します。

// ./storybook/main.js

  webpackFinal: async (config) => {
    ~~ 省略 ~~
    config.module.rules.push({
      test: /\.svg$/,
      use: ['@svgr/webpack'],
    })

    return config
  },

この状態でStorybookのビルドを実行すると、 TypeError: this.getOptions is not a function が発生します。

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

この問題はWebpack5を使うように修正すれば解決するとのことでした。ref: