Next.js + Storybook

この文書では、Next.js のプロジェクトに Storybook を追加して利用する方法を紹介します。Storybook を利用すると、事前に用意したデータを利用してコンポーネントを表示することができるため、プログラムの開発と並行してコンポーネントの UI を作成していくことができます。

プロジェクトの作成

まず最初に、Next.js のプロジェクトを作成し、続いて Storybook のインストールをします。

Next.js のプロジェクトの作成

プロジェクトの作成として、Next.js + Tailwind CSS のプロジェクトを作成します。

sh
Image

なお、標準のテンプレートで表示される postcss.config.mjs の設定では Storybook のインストールの時にエラーが表示されます。作成時のファイルは以下のようになっています。

postcss.config.mjs

これを以下のように書き換えてください。

postcss.config.mjs

上記の変更はインストールをそのまま実行するとエラーメッセージとして表示されます。あらかじめ変更しておきましょう。

Image

Storybook のインストール

インストールの手順としては、Next.js の場合は公式サイトの React の手順で進めていきます。

以下のコマンドでインストールを進めます。

sh

インストーラーが新しくインストールを実行するのかの確認を表示します。

Image

しばらくすると、Storybook の画面が表示されます。

Image

インストールが完了したターミナルの画面は以下の通りです。

Image

ファイルの確認

Next.js に Storybook を追加した際の変更点を確認していきます。Visual Studio Code で変更点を見ると以下のようになります。

Image

変更点だけをピックアップすると以下のようになります。

  • .storybook- storybook layout files
    • package.json- install storybook package
    • vitest.config.ts- config for Vitest
    • vitest.shms.d.ts- global type definitions for Vitest

    インストール後の動作確認で npm run build を実行すると以下のようなエラーが表示されます。

    Image

    これは、src/stories/Page.tsx のファイルの 43 行目で "args" という記述があり、これが ESlint でエラーになっています。以下のように書き換えてください。

    html

    これで build の実行が可能となりました。

    Storybook の動作確認

    現在のプロジェクトでは、コマンドを実行することで Next.js と Storybook が共存している形です。まず、Next.js を起動するときは以下のコマンドです。

    sh

    これで Next.js が http://localhost:3000 で起動します。

    また Storybook を起動するときは以下のコマンドで起動します。

    sh

    これで Storybook が http://localhost:6006/ と Next.js とは別のポートで起動します。このため、同じプロジェクトで2つのプログラムが動くことがわかります。

    なお、Storybook で作成したコンポーネントを build をして静的サイトとして展開することもできます。この場合は以下のコマンドで実行します。

    sh

    以下のように build が実行されます。

    Image

    そしてサイトは storybook-static に展開しています。

    Image

    Tailwind CSS を利用する

    Storybook を設定した段階では、Next.js で利用している Tailwind CSS を参照していない状態です。そこで、Tailwind CSS を参照する形に Storybook の設定を変更していきます。

    スタイルシートの整理

    スタイルシートのファイルを整理していきます。

    1. 既存のプロジェクトでは Next.js の初期の状態となるため、src/app/globals.css に Tailwind CSS で利用するファイルが適用されています。これを、src/styles/globals.css に移動します。
    2. src/stories のフォルダの中に含まれる css ファイルを上記と同様に src/styles に移動します
    3. 移動したスタイルシートを、globals.css の import で読み込むようにします。
    src/styles/globals.css

    styles のフォルダの中は以下のようになります。

        • button.css
        • globals.css
        • header.css
        • page.css

    また、src/app/layout.tsx のファイルで読み込んでいるスタイルシートのパスも変更となるため、以下のように変更をします。

    src/app/layout.tsx

    スタイルシートの設定としては、storybook が参照できるようにするために、以下のファイルもスタイルシートを読み込むように変更をします。

    .storybook/preview.ts

    これで、スタイルシートの調整は完了しました。

    components フォルダの作成

    Next.js で利用するコンポーネントとして、storybook で用意しているコンポーネントを利用できるように、以下のように変更をします。

    1. src/stories/Configure.mdx と src/stories/assets を削除します
    2. src/stories のフォルダを src/components のフォルダに変更します。
    3. src/components/Button.tsx 、src/components/Header.tsx および src/components/Page.tsx で読み込んでいる css の行を削除します

    続いて上記のコンポーネントを Storybook が認識できるように変更を進めます。まず、.storybook/main.ts において、今回作成をした components のフォルダの配下にファイルを配置しているように設定を変更します。

    .storybook/main.ts

    上記の変更で、Next.js で作成をするコンポーネントに対して、stories.ts のファイルを定義して、コンポーネントの表示ができるようになりました。

    コンポーネントの更新

    今回の Next.js のプロジェクトは App Router としているため、Button.tsx および Page.tsx はクライアント側での処理が追加されているため、以下の1行を追加する必要があります。

    tsx

    これで Next.js で利用できるコンポーネントになりました。

    ただし、このコードを入れている場合 storybook で build を実行するとエラーが表示されます。以下のような画面が表示される形です。

    Image

    前半の警告はまさに use client を追加したところが問題となっています。また後半の警告はサイズが大きくなっていることを示しています。

    これを回避するために、.storybook/main.ts のファイルに以下のコードを追加します。

    .storybook/main.ts

    これで警告が表示されない形となりました。

    Storybook のファイル構成

    最後に Storybook で定義している stories.tsx ファイルの役割を紹介します。まず、 Button.tsx のための定義ファイル src/components/Button.stories.ts を上から順に機能を紹介していきます。

    src/components/Button.stories.ts

    上記のコードは、同じフォルダにある Button.tsx に対する stories.ts になっていることを定義しています。

    src/components/Button.stories.ts

    これは Storybook の画面において表示される内容の定義になります。

    コンポーネントで利用するデータの定義を設定する際には、argTypes の項目を増やすことで対応が可能です。最後の以下の項目で、表示をする場合の値を設定して、サンプルを表示できるようにしています。

    src/components/Button.stories.ts

    ダークモードの追加

    Storybook を利用することで、ライトモード、ダークモードの切り替えを画面上で変更可能となります。これを活用すると、コンポーネントの作成、確認の作業が非常にやりやすくなります。

    Storybook の設定

    まずは Storybook 側の設定を進めていきます。

    sh

    続いて Storybook の設定ファイルにインストールをした Addon を追加します。

    .storybook/main.ts

    Storybook が表示する際に、Next.js と同じように Class を指定してモードの切り替えをするように、withThemeByClassName の関連コードを追加します。

    .storybook/preview.ts

    Tailwind CSS の設定

    この設定は簡単で、globals.css ファイルに以下の行を追加するだけでダークモードが動作するようになります。

    src/styles/globals.css

    Card コンポーネントを追加する

    ダークモードに対応した Card コンポーネントを作成していきます。まず、Card コンポーネントを以下のように作成します。

    Card コンポーネントでは画像をアセットとして利用したいため、先にアセットの Interface を追加します。

    src/types/asset.ts

    この Asset の定義を利用して、Card で扱うデータ項目を設定します。今回、Card の画像の位置に関しては top と left を用意しました。

    src/components/Card.tsx

    このカードのスタイルシートを以下のように作成しています。

    src/styles/card.css

    また Storybook のプレビューで確認するときにダークモードが有効になるように、以下のスタイルシートも作成をします。

    src/styles/storybook.css

    両方のファイルを globals.css で読み込んでください。今回はサンプルのスタイルも削除しました。

    src/styles/globals.css

    最後に、コンポーネントのサンプルを表示するファイルを以下のように作成をします。

    src/components/Card.stories.ts

    なお、public に画像をコピーして、その画像ファイルを参照するように実装しています。

    動作確認

    それでは実際の動作確認を進めます。以下のコマンドを実行します。

    tsx

    Storybook が起動すると、今回追加をしたボタンが左側のメニューに追加されています。選択をすると以下のような画面になります。

    Image

    モードの切替ボタンをクリックして、ダークモードにします。

    Image

    意図した形でダークモードでの色が設定できています。続いて、画像の位置を左側にした場合の動作を確認すると、以下のような形で左側の時の表示も確認できました。

    Image

    これでダークモードでの動作、そして表示に関するテストができました。

    Vercel に展開する

    今回作成をした Storybook のデータをいつでもサイトで参照できるように、Vercel に展開していきます。

    1. Vercel で New Project を開く
    2. 該当するリポジトリを指定する
    3. Framework Preset を Storybook を選択する
    Image

    環境変数などはないため、追加の設定なしに展開をすることが可能です。しばらくすると、以下のように参照できるようになりました。

    Image

    まとめ

    今回は Next.js App Router に対して Storybook をインストール、そして Tailwind CSS を共有するところまで進めていきました。今回実施したサンプルのコードは以下のリポジトリ、およびデモサイトを参照できるようにしてあります。