Next.jsプロジェクトにStorybookを導入したときに困ったこと

2021.12.09

こんにちは!DA(データアナリティクス)事業本部 サービスソリューション部の大高です。

UIコンポーネントのデザイン・管理に便利なツールStorybookですが、Next.jsのプロジェクトにも導入することができます。

今回、以下の記事を参考に実際に導入してみたところ、いくつかうまく動かすことができず困ったことがあったのでまとめてみたいと思います。

前提

Next.jsのバージョンは 12 を利用しています。また、言語はTypescriptでプロジェクトを作成しており、スタイル設定には*.scssのファイルを利用しています。

導入方法

基本的に記事で紹介されているYoutubeの動画を見ながら進めました。細かい手順は省略し「困ったところ」と「その解決方法」にフォーカスしたいと思います。

困ったところ

3点困ったところがあり、いくつかのサイトを参考にさせていただきつつ、対応を行いました。困った内容と対応方法は以下のとおりです。

導入後に yarn storybook をすると Cannot find module エラーが出る

sb initでStorybookを導入後に起動すると、以下の通りのエラーが発生しました。

$ yarn storybook
yarn run v1.22.15
$ start-storybook -p 6006
info @storybook/react v6.4.3
info 
info => Loading presets
info => Using implicit CSS loaders
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'

調べたところ、以下のようなGithubのIssueを見つけました。

対処方法としては、下記コメントで言及されているとおり.storybook/main.jsを修正することで対処できました。

.storybook/main.js

module.exports = {
  "typescript" : { reactDocgen: false },
  "stories": [
    "../stories/**/*.stories.mdx",
    "../stories/**/*.stories.@(js|jsx|ts|tsx)"
  ],
  "addons": [
    "@storybook/addon-links",
    "@storybook/addon-essentials"
  ],
  "framework": "@storybook/react",
  "core": {
    "builder": "webpack5"
  }
}

Next.jsで作成済みのコンポーネントを指定したstoryを追加すると ModuleParseError が出る

次に、Next.jsで作成済みのコンポーネントを指定したstoryを追加して表示しようとしたところ、以下のようなエラーが発生しました。

ModuleNotFoundError: Module not found: Error: Can't resolve 'fs' in '/home/foo-bar/src/foo-bar/lib'

このコンポーネントではfspathパッケージを利用しており、これによりエラーが起きていました。

こちらについては、パッケージに対するPolyfillを含まないように、以下のようにwebpackFinalの箇所でfallback設定を行いました。

.storybook/main.js

module.exports = {
  typescript: { reactDocgen: false },
  stories: [
    "../stories/**/*.stories.mdx",
    "../stories/**/*.stories.@(js|jsx|ts|tsx)",
  ],
  addons: [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "storybook-addon-designs",
  ],
  framework: "@storybook/react",
  core: {
    builder: "webpack5",
  },
  webpackFinal: async (config, { configType }) => {
    // Fixes npm packages that depend on some modules
    config.resolve = {
      extensions: [".ts", ".tsx", ".js", ".css", ".scss"],
      fallback: {
        fs: false,
        path: false,
      },
    };

    // Important: return the modified config
    return config;
  },
};

参考

SCSSのファイルがうまくロードできない

SCSSのファイルを利用している箇所のビルドで、以下のエラーが発生しました。

You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders

このエラーについては、下記の記事を参考にさせていただき対応しました。

対応としては、ローダーのインストールと設定ファイルの修正が必要でしたので、それぞれ以下のように対応しました。

$ yarn add -D css-loader sass-loader style-loader

.storybook/main.js

const path = require("path");

module.exports = {
  typescript: { reactDocgen: false },
  stories: [
    "../stories/**/*.stories.mdx",
    "../stories/**/*.stories.@(js|jsx|ts|tsx)",
  ],
  addons: [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    // 'storybook-addon-designs'
  ],
  framework: "@storybook/react",
  core: {
    builder: "webpack5",
  },
  webpackFinal: async (config, { configType }) => {
    // Fixes npm packages that depend on `fs` module
    config.resolve = {
      extensions: [".ts", ".tsx", ".js", ".css", ".scss"],
      fallback: {
        fs: false,
        path: false,
      },
    };

    // Sass & CSS Modules
    config.module.rules.push({
      test: /\.scss$/,
      use: [
        "style-loader",
        {
          loader: "css-loader",
          options: {
            modules: {
              auto: true,
            },
          },
        },
        "sass-loader",
      ],
      include: path.resolve(__dirname, "../"),
    });

    // Important: return the modified config
    return config;
  },
};

ここまでの対応で、無事にStorybookでNext.jsプロジェクトの既存コンポーネントを表示することができました!

まとめ

以上、Next.jsプロジェクトにStorybookを導入したときに困ったことでした。

Webpackまわりに慣れているとすぐに気づきそうなエラーでしたが、普段あまり気にすることのないところだったので少しハマってしまいました。

どなたかのお役に立てば幸いです。それでは!