📖

nextjsでstorybookの環境構築を行う

2023/05/27に公開

はじめに

環境構築する際に毎回調べるのも大変なので備忘録風にnextjsでstorybookの設定をする方法を書いておきます。

1.プロジェクトの作成

以下コマンドを実行してnextjsのプロジェクトを作成してください

npx create-next-app myapp --ts

生成時の対話はそれぞれ自分に合った設定を行ってください
今回は以下のようにしました

✔ Would you like to use ESLint with this project? …  Yes 
✔ Would you like to use `src/` directory with this project? …  Yes
✔ Would you like to use experimental `app/` directory with this project? … No 
✔ What import alias would you like configured? … @/*

2.storybookを初期化

以下コマンドを実行してstorybookの初期化を行います。
npx sb init

こちらの質問はYにしときました

? We have detected that you're using ESLint. Storybook provides a plugin that gives the best experience with Storybook and helps follow best practices: https://github.com/storybookjs/eslint-plugin-storybook#readme

Would you like to install it? › (Y/n)

初期化が終わるとpackage.jsonに以下が追加されます

package.json

  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
+   "storybook": "storybook dev -p 6006",
+   "build-storybook": "storybook build"
  },

以下コマンドがstorybookを起動するコマンドです。
npm run storybook

storybookはデフォルトではlocalhost:6006で動いています
localhost:6006にアクセス

実際にコマンドを実行してlocalhost:6006に以下のように表示されれば成功です。

3.storybookの使い方

storybookではデフォルト設定でhoge.stories.[拡張子]というファイルを作ることでstorybookにプレビューとして表示されます。
この設定は.storybook/main.tsで宣言されています。

.storybook/main.ts
import type { StorybookConfig } from "@storybook/nextjs";
const config: StorybookConfig = {
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],←ここ!!!!
addons: [
  "@storybook/addon-links",
  "@storybook/addon-essentials",
  "@storybook/addon-interactions",
],
framework: {
  name: "@storybook/nextjs",
  options: {},
},
docs: {
  autodocs: "tag",
},
};
export default config;

デフォルト設定ではsrcディレクトリ内のmdxファイル、.stories.ts,.stories.tsx,.stories.js,.stories.jsxが読み込まれるようになっています。
storybookの初期化を行うとサンプルファイルが作られます。
以下がそのサンプルです

src/stories/Header.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Header } from './Header';

const meta: Meta<typeof Header> = {
title: 'Example/Header',
component: Header,
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
tags: ['autodocs'],
parameters: {
  // More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout
  layout: 'fullscreen',
},
};

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

export const LoggedIn: Story = {
args: {
  user: {
    name: 'Jane Doe',
  },
},
};

export const LoggedOut: Story = {};

  • const meta オブジェクトのメタデータを宣言しています

    • title:storybook上に表示されるそのコンポーネントの名前です
    • component:どのコンポーネントを表示するか(サンプルはHeaderコンポーネント)
    • tags:コンポーネントにタグづけができる(タグによって分類など)
    • parameters:コンポーネントのレイアウトなどを設定できる
  • type Story = StoryObj<typeof Header>;
    Headerコンポーネントに関するオブジェクトが持つ型情報の宣言

  • export const LoggedIn: Story:Story型のオブジェクトを生成してログインしている状態のstoryオブジェクトをexport

    4.storybookの設定を行う

    storybookではコンポーネント単位の開発を行うことができます。
    基本的にはデフォルト設定である程度のことはどうにかできます。
    しかしながらたとえばMUIthemeproviderを使いたい時、デフォルトの設定ではcustomThemeを適用できません
    今回はMUIを例に設定を変更したいと思います。

.storybook/preview.tsx
+import { ThemeProvider } from "@emotion/react";
+import { CssBaseline, createTheme } from "@mui/material";
import type { Preview } from "@storybook/react";
+import React from "react";

+const theme = createTheme({
+    components: {
+        MuiButton: {
+            styleOverrides: {
+                root: {
+                    backgroundColor: "red",
+                },
+            },
+        },
+    },
+});

+export const decorators = [
+    (Story) => (
+        <ThemeProvider theme={theme}>
+            <CssBaseline />
+            <Story />
+        </ThemeProvider>
+    ),
+];
const preview: Preview = {
    parameters: {
        actions: { argTypesRegex: "^on[A-Z].*" },
        controls: {
            matchers: {
                color: /(background|color)$/i,
                date: /Date$/,
            },
        },
    },
};

export default preview;

decoratorsとして配列に要素を返す関数を入れることでstoryをグローバルにラップすることができます。
これはrecoilなどにも使用できます。
createThemeは別個で作るよりはすでに作られているならそちらを流用するほうが実装として良いです。

最後に

ちょっとしたメモ程度の記事ですが、皆様の参考になれば幸いです。
もっと詳しくstorybookに関して知りたい人は公式ドキュメントをご覧ください。

Discussion