T-CREATOR

Storybook でよくあるエラーと解決策まとめ

Storybook でよくあるエラーと解決策まとめ

Storybook を使った開発において、多くの開発者が同じようなエラーに遭遇します。 このガイドでは、よく発生するエラーパターンを種類別に整理し、具体的な解決策を提示します。初心者の方から経験者まで、効率的にトラブルシューティングできるよう実際のエラーメッセージとともに解説いたします。

背景

Storybook は UI コンポーネントの開発とテストを効率化する強力なツールです。 React、Vue、Angular などの主要フレームワークに対応し、コンポーネントの独立した開発環境を提供します。

しかし、その複雑な設定と多様な連携機能により、セットアップから実際の開発まで様々な場面でエラーが発生しやすいのも事実です。 特に以下の要因でエラーが頻発します。

mermaidflowchart TD
    A[Storybook プロジェクト] --> B[セットアップ段階]
    A --> C[開発段階]
    A --> D[デプロイ段階]
    
    B --> E[パッケージ依存関係]
    B --> F[設定ファイル]
    C --> G[コンポーネント連携]
    C --> H[アドオン機能]
    D --> I[ビルド処理]
    
    E --> J[バージョン競合]
    F --> K[webpack 設定]
    G --> L[インポートエラー]
    H --> M[プラグイン競合]
    I --> N[静的ファイル生成]

図で示すように、開発フェーズごとに異なる原因でエラーが発生し、それぞれ特有の対処法が必要になります。

課題

Storybook 開発で特によく発生するエラーパターンには以下のような特徴があります。

エラー発生の主な要因

要因発生頻度影響度解決難易度
パッケージバージョン不整合
設定ファイルの記述ミス
TypeScript 型エラー
webpack 設定競合
アドオン機能競合

これらのエラーは開発の進行を大幅に遅らせる可能性があります。 特に初心者の場合、エラーメッセージの意味を理解するだけでも時間がかかり、適切な解決策を見つけるまでに多大な労力を要します。

また、同じエラーでも環境やプロジェクト構成によって解決方法が異なるため、一般的な解決策では対応できないケースも多々あります。

解決策

セットアップ時のエラー

インストールエラー

よくあるエラー:npm/yarn インストール失敗

bashnpm ERR! peer dep missing: react@">=16.8.0", required by @storybook/react@6.5.16

このエラーは peer dependencies の不整合で発生します。

解決手順:

bash# 1. 現在のnode_modulesを削除
rm -rf node_modules package-lock.json

# 2. Reactのバージョンを確認
yarn list react
bash# 3. 適切なStorybookバージョンをインストール
yarn add -D @storybook/react@latest @storybook/addon-essentials@latest

よくあるエラー:Node.js バージョン不適合

basherror @storybook/core@6.5.16: The engine "node" is incompatible with this module. Expected version ">=14.0.0".

解決手順:

bash# Node.jsバージョン確認
node --version

# nvmでバージョン管理している場合
nvm use 16
nvm alias default 16

初期化エラー

よくあるエラー:Storybook 初期化失敗

bashnpx storybook@latest init
bashError: No supported framework detected. Please check your package.json

このエラーは package.json にフレームワークの依存関係が適切に記載されていない場合に発生します。

解決手順:

json// package.json に必要な依存関係を追加
{
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  }
}
bash# 依存関係インストール後に再実行
yarn install
npx storybook@latest init

設定ファイルエラー

よくあるエラー:main.js 設定エラー

javascript// .storybook/main.js
module.exports = {
  stories: ['../src/**/*.stories.@(js|jsx|ts|tsx)'],
  addons: [
    '@storybook/addon-essentials'
  ],
}
bashError: Cannot resolve '../src/**/*.stories.@(js|jsx|ts|tsx)'

解決手順:

javascript// .storybook/main.js - 正しい設定
module.exports = {
  stories: [
    '../src/**/*.stories.@(js|jsx|ts|tsx|mdx)'
  ],
  addons: [
    '@storybook/addon-essentials',
    '@storybook/addon-links',
    '@storybook/addon-docs'
  ],
  framework: {
    name: '@storybook/react-webpack5',
    options: {}
  }
}

ビルド・起動時のエラー

webpack設定エラー

よくあるエラー:モジュール解決エラー

bashModule not found: Error: Can't resolve '@/components' in '/src/stories'

これは webpack のエイリアス設定が Storybook に反映されていない場合に発生します。

解決手順:

javascript// .storybook/main.js にwebpack設定を追加
const path = require('path');

module.exports = {
  // 既存の設定...
  webpackFinal: async (config) => {
    config.resolve.alias = {
      ...config.resolve.alias,
      '@': path.resolve(__dirname, '../src'),
    };
    return config;
  },
}

よくあるエラー:CSS/SCSS ローダーエラー

bashModule parse failed: Unexpected character '@' (1:0)
You may need an appropriate loader to handle this file type

解決手順:

javascript// .storybook/main.js にCSSローダー設定を追加
module.exports = {
  // 既存の設定...
  webpackFinal: async (config) => {
    config.module.rules.push({
      test: /\.scss$/,
      use: ['style-loader', 'css-loader', 'sass-loader'],
      include: path.resolve(__dirname, '../'),
    });
    return config;
  },
}

ポート競合エラー

よくあるエラー:デフォルトポート使用中

bashError: listen EADDRINUSE: address already in use :::6006

解決手順:

bash# 1. 使用中のプロセスを確認
lsof -i :6006

# 2. プロセスを終了
kill -9 <PID>
bash# 3. 別のポートで起動
yarn storybook --port 6007
json// package.json でデフォルトポートを変更
{
  "scripts": {
    "storybook": "storybook dev -p 6007"
  }
}

依存関係エラー

よくあるエラー:バージョン競合

bashnpm WARN peer dep missing: webpack@"^5.0.0", required by @storybook/react@7.0.0

解決手順:

bash# 1. 依存関係の確認
yarn why webpack

# 2. 必要なバージョンをインストール
yarn add -D webpack@^5.0.0
bash# 3. peer dependenciesの自動解決
yarn install --peer

コンポーネント表示エラー

インポートエラー

よくあるエラー:コンポーネントインポート失敗

bashError: Cannot resolve './Button' from 'src/stories/Button.stories.ts'

解決手順:

typescript// Button.stories.ts - 正しいインポート記述
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from '../components/Button'; // 相対パスを明確に

const meta: Meta<typeof Button> = {
  title: 'Example/Button',
  component: Button,
};

export default meta;
type Story = StoryObj<typeof Button>;

よくあるエラー:デフォルトエクスポートなし

bashAttempted import error: './Button' does not contain a default export

解決手順:

typescript// Button.tsx - 名前付きエクスポートの場合
export const Button = ({ label, ...props }) => {
  return <button {...props}>{label}</button>;
};

// Button.stories.ts - 対応するインポート
import { Button } from './Button';

Props型エラー

よくあるエラー:TypeScript型定義エラー

bashType '{ onClick: () => void; }' is missing the following properties from type 'ButtonProps': label, size

解決手順:

typescript// Button.tsx - 型定義を明確に
interface ButtonProps {
  label: string;
  size?: 'small' | 'medium' | 'large';
  onClick?: () => void;
}

export const Button = ({ label, size = 'medium', ...props }: ButtonProps) => {
  return (
    <button className={`btn btn-${size}`} {...props}>
      {label}
    </button>
  );
};
typescript// Button.stories.ts - 型安全なStory定義
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';

const meta: Meta<typeof Button> = {
  title: 'Example/Button',
  component: Button,
  argTypes: {
    size: {
      control: { type: 'select' },
      options: ['small', 'medium', 'large'],
    },
  },
};

export default meta;
type Story = StoryObj<typeof Button>;

export const Primary: Story = {
  args: {
    label: 'Button',
    size: 'medium',
  },
};

CSS/スタイルエラー

よくあるエラー:スタイルシート読み込み失敗

bashModule not found: Error: Can't resolve './Button.module.css'

解決手順:

javascript// .storybook/main.js にCSS Modulesサポートを追加
module.exports = {
  webpackFinal: async (config) => {
    config.module.rules.push({
      test: /\.module\.css$/,
      use: [
        'style-loader',
        {
          loader: 'css-loader',
          options: {
            modules: true,
          },
        },
      ],
    });
    return config;
  },
}

よくあるエラー:グローバルCSS適用されない

javascript// .storybook/preview.js でグローバルスタイルをインポート
import '../src/styles/globals.css';

export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
  controls: {
    matchers: {
      color: /(background|color)$/i,
      date: /Date$/,
    },
  },
}

アドオン関連エラー

アドオンインストールエラー

よくあるエラー:アドオン依存関係競合

bashnpm ERR! peer dep missing: @storybook/addon-docs@"^6.0.0", required by @storybook/addon-knobs@6.4.0

解決手順:

bash# 1. 互換性のあるバージョンを確認
yarn info @storybook/addon-knobs peerDependencies

# 2. 適切なバージョンをインストール
yarn add -D @storybook/addon-knobs@^6.4.0 @storybook/addon-docs@^6.0.0
javascript// .storybook/main.js でアドオンを有効化
module.exports = {
  addons: [
    '@storybook/addon-essentials',
    '@storybook/addon-knobs'
  ],
}

設定競合エラー

よくあるエラー:アドオン設定重複

bashWarning: Duplicate addon "@storybook/addon-docs" detected. Please remove one instance.

解決手順:

javascript// .storybook/main.js - 重複を避ける設定
module.exports = {
  addons: [
    '@storybook/addon-essentials', // addon-docsは含まれているため除外
    '@storybook/addon-links',
    // '@storybook/addon-docs', // 削除
  ],
}

バージョン互換性エラー

よくあるエラー:Storybook本体とアドオンのバージョン不整合

bashError: Addon "@storybook/addon-viewport" is not compatible with Storybook 7.0.0

解決手順:

bash# 1. Storybookと互換性のあるアドオンバージョンを確認
yarn info @storybook/addon-viewport versions --json

# 2. 互換バージョンをインストール
yarn add -D @storybook/addon-viewport@^7.0.0
javascript// package.json でバージョンを統一
{
  "devDependencies": {
    "@storybook/react": "^7.0.0",
    "@storybook/addon-essentials": "^7.0.0",
    "@storybook/addon-viewport": "^7.0.0"
  }
}

具体例

実際のプロジェクトでの解決事例

ケース1:Next.js プロジェクトでの画像インポートエラー

エラーメッセージ:

bashError: Module not found: Can't resolve '/public/images/logo.png'

発生状況: Next.js プロジェクトで public フォルダの静的ファイルにアクセスしようとした際に発生。

解決手順:

javascript// .storybook/main.js に静的ファイルディレクトリを設定
module.exports = {
  staticDirs: ['../public'],
  webpackFinal: async (config) => {
    // 絶対パスでの画像参照を相対パスに変換
    config.module.rules.push({
      test: /\.(png|jpe?g|gif|svg)$/,
      use: {
        loader: 'file-loader',
        options: {
          publicPath: '/images/',
          outputPath: 'images/',
        },
      },
    });
    return config;
  },
}
typescript// コンポーネント内での正しい画像参照
import Image from 'next/image';

const Logo = () => {
  return (
    <Image
      src="/images/logo.png" // publicフォルダからの相対パス
      alt="Logo"
      width={200}
      height={100}
    />
  );
};

ケース2:TypeScript 絶対インポートパスエラー

エラーメッセージ:

bashModule not found: Error: Can't resolve '@/types/User' in '/src/components'

発生状況: TypeScript の絶対インポートパス(@/ エイリアス)が Storybook で認識されない。

解決手順:

javascript// .storybook/main.js にTypeScript設定を同期
const path = require('path');

module.exports = {
  typescript: {
    check: false,
    checkOptions: {},
    reactDocgen: 'react-docgen-typescript',
    reactDocgenTypescriptOptions: {
      shouldExtractLiteralValuesFromEnum: true,
      propFilter: (prop) => (prop.parent ? !/node_modules/.test(prop.parent.fileName) : true),
    },
  },
  webpackFinal: async (config) => {
    config.resolve.alias = {
      ...config.resolve.alias,
      '@': path.resolve(__dirname, '../src'),
      '@/types': path.resolve(__dirname, '../src/types'),
      '@/components': path.resolve(__dirname, '../src/components'),
    };
    return config;
  },
}
json// tsconfig.json の設定と同期させる
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "@/types/*": ["src/types/*"],
      "@/components/*": ["src/components/*"]
    }
  }
}

ケース3:Material-UI テーマプロバイダーエラー

エラーメッセージ:

bashError: useTheme() may only be used in a component tree that contains a ThemeProvider

発生状況: Material-UI(MUI)を使用するコンポーネントで、テーマプロバイダーが適用されていない。

解決手順:

typescript// .storybook/preview.tsx にテーマプロバイダーを設定
import React from 'react';
import { ThemeProvider, createTheme } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';

const theme = createTheme({
  palette: {
    primary: {
      main: '#1976d2',
    },
  },
});

export const decorators = [
  (Story) => (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <Story />
    </ThemeProvider>
  ),
];
typescript// コンポーネントStoryでの個別テーマ適用
import type { Meta, StoryObj } from '@storybook/react';
import { ThemeProvider, createTheme } from '@mui/material/styles';
import { Button } from '@mui/material';

const darkTheme = createTheme({
  palette: {
    mode: 'dark',
  },
});

const meta: Meta<typeof Button> = {
  title: 'MUI/Button',
  component: Button,
  decorators: [
    (Story) => (
      <ThemeProvider theme={darkTheme}>
        <Story />
      </ThemeProvider>
    ),
  ],
};

まとめ

Storybook でのエラー対処において重要なのは、エラーの分類と段階的なアプローチです。

エラー予防のベストプラクティス

段階予防策確認ポイント
セットアップバージョン管理の徹底package.json の依存関係確認
開発型安全性の確保TypeScript 設定の同期
設定段階的な機能追加アドオンの個別テスト
デプロイビルド検証の自動化CI/CD パイプライン整備

効率的なデバッグ手順

mermaidflowchart LR
    A[エラー発生] --> B{エラー種類判定}
    B -->|セットアップ| C[依存関係確認]
    B -->|ビルド| D[webpack設定確認]
    B -->|表示| E[インポート確認]
    B -->|アドオン| F[バージョン確認]
    
    C --> G[package.json修正]
    D --> H[設定ファイル修正]
    E --> I[パス・型修正]
    F --> J[互換バージョン適用]
    
    G --> K[解決確認]
    H --> K
    I --> K
    J --> K

継続的な改善のために

  • ドキュメント化:解決したエラーと手順を記録
  • 設定の標準化:プロジェクトテンプレートの作成
  • 定期更新:依存関係の定期的なアップデート
  • チーム共有:ナレッジベースの構築

これらの対策により、Storybook 開発での生産性を大幅に向上させることができます。 エラーに遭遇した際は、まず分類を行い、該当する解決策を段階的に適用していくことで、効率的な問題解決が可能になります。

関連リンク