メインコンテンツへスキップ

Storybook Astro導入時にハマった箇所のメモ

·2471 文字·5 分
称徳寺 涼雨
著者
称徳寺 涼雨
プリズムスタァ

Astroプロジェクトへ試験的にStorybook Astroを導入してみました。
このプロジェクトにはAstroコンポーネントだけでなくReactコンポーネントも含まれており、両方を同じStorybook上でプレビューできる構成を目指しましたが、
導入の過程で複数のエラーに遭遇したので、それぞれの原因と解決方法を記録しておく。

Storybook Astroとは
#

Storybook Astroは、Astro向けのコミュニティ製Storybookフレームワークです。
公式サイトによれば、Astroコンポーネントをサーバーサイドでレンダリングしつつ、React、Vue、Svelte、Solid、Preact、Alpine.jsといったUIフレームワークのコンポーネントも同じStorybook上でプレビューできます。

導入前に調べた際の注意点
#

AstroとStorybookの組み合わせを調べた際、同じ「storybook-astro」という名前を持つパッケージが複数見つかった。
今回使用したstorybook-astro/storybook-astro@storybook-astro/framework)は、Storybook公式ドキュメントのフレームワーク一覧にも掲載されている、コミュニティ支援を受けた本流のプロジェクトである。

同じ名前でも中身がまったく別のパッケージがあるため、npmでインストールする際はパッケージ名がスコープ付きの@storybook-astro/frameworkになっているかを確認する必要がある。

Reactコンポーネントのstoryが表示されない
#

Reactコンポーネントのstoryを開くと、Renderer 'astro' not found. Available renderers: reactというエラーが出て描画に失敗した。

原因は@storybook-astro/frameworkの仕様にあった。
このフレームワークは@storybook-astro/renderer/entry-preview.jsの仕様により、プロジェクト全体にparameters.renderer = "astro"をデフォルトで適用する。
Reactコンポーネントのstoryでもこのデフォルト値がそのまま使われてしまい、レンダラーの不一致でエラーになっていた。

対応として、metaparameters: { renderer: "react" }を明示的に指定が必要で、Astroコンポーネントのstoryにはこの指定は不要のようです。

import type { Meta } from "@storybook/react";
import { Button } from "./Button";

const meta: Meta<typeof Button> = {
  title: "app/components/Button",
  component: Button,
  parameters: {
    renderer: "react", // 追加
  },
};

export default meta;

ボタンは表示されるが装飾がない
#

これはAstroに関係ないのですが、エラーは解消されてボタンは表示されたが、Tailwindのスタイルが一切適用されていなかった。

原因は、Tailwindのグローバルスタイル(src/styles/global.css)がStorybookのプレビューに読み込まれていないことだった。
起動ログを確認すると@tailwindcss/viteプラグイン自体は自動で読み込まれていたため、CSSのimportさえ追加すればTailwindは動く状態だった。

対応として、.storybook/preview.tsに下記のようなCSSのimportを追加した。

import "../src/styles/global.css";

tags: [“autodocs”]を指定すると型エラーになる
#

preview.tsPreview型を使いtags: ["autodocs"]を含む設定オブジェクトを書いたところ、型エラーが発生した。

原因は、@storybook-astro/frameworkがStorybookのCSF4形式を採用していることだった。
CSF4におけるPreview型は、definePreview()が返す内部オブジェクトの型(_taginputcomposedなどを持つ)であり、tagsを直接持つプレーンな設定オブジェクトの型ではない。

対応として、設定をdefinePreview()関数を通して渡す形に書き換えた。

import { definePreview } from "@storybook-astro/framework";
import "../src/styles/global.css";

export default definePreview({
  tags: ["autodocs"],
  parameters: {
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/i,
      },
    },
  },
});

docsページは出るが、中身が空白
#

main.tsにaddonを追加した結果、Docsページ自体は表示されるようになったが、中身は空白のままだった。
ブラウザで実際にページを開き、コンソールのpageerrorを確認したところ、docsParameter.renderer is not a functionというエラーが出ていた。

原因は、CSF4形式ではmain.tsのaddons配列にパッケージ名を書くだけでは、アドオンのpreview annotationsが読み込まれないことにあった。
生成されるproject-annotations.jsを確認すると、preview.ts側のdefinePreview(...).composedだけが参照されており、main.ts側のaddons設定は反映されていなかった。
その結果、Docsページを描画するparameters.docs.renderer関数自体が存在せず、画面が空白になっていた。

対応として、preview.ts側で@storybook/addon-docsのデフォルトエクスポートをdefinePreview()addons配列に明示的に渡した。

import { definePreview } from "@storybook-astro/framework";
import addonDocs from "@storybook/addon-docs"; // 追加
import "../src/styles/global.css";

export default definePreview({
  addons: [addonDocs()], // 追加
  tags: ["autodocs"],
  parameters: {
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/i,
      },
    },
  },
});

まとめ
#

  • @storybook-astro/frameworkはCSF4形式を採用しているため、main.tsのaddons配列だけで完結するClassic API方式の設定は一部しか機能しない。
  • Reactコンポーネントのstoryにはparameters: { renderer: "react" }の明示指定が必須。
  • docsアドオンのようなpreview annotationsはpreview.ts側のdefinePreview()にも渡す必要がある。

関連パッケージのバージョン
#

  • @storybook-astro/framework@1.9.0
  • storybook@10.5.4
  • @storybook/builder-vite@10.5.4
  • @storybook/react@10.5.4

参考リンク
#