🎱

Storybook 8 がリリースされたので早速アップグレードしてみた (React/Next.js)

2024/03/21に公開

背景

2023年12月頃に alpha 版がリリース、その後 beta, RC と段階を踏んでいた Storybook 8 が、2024年3月13日に正式リリース[1]されました 🎉

https://storybook.js.org/blog/storybook-8/

シンプルなプロジェクトであれば npx storybook@latest upgrade でいい感じにアップグレードしてくれるのですが、少し複雑な修正が必要だとうまく行かないことも多く、今回もその例に漏れずエラーが出てしまったため、手動であれこれ対応しながら 7.6.6 から 8.x にアップグレードしました。[2]

すべてを網羅している訳ではなくあくまで私のプロジェクト[3]で対応が必要だった内容をまとめたものとなりますので、必ず公式のマイグレーションガイドも参照ください。

https://storybook.js.org/docs/migration-guide

https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#from-version-7x-to-800

やったこと

Storybook 関連のライブラリのバージョンアップ

公式の storybook および @storybook/* ライブラリの 8.x へのバージョンアップを行いました。

非公式のライブラリとして storycap を使用していますが、とても有り難いことに早くも Storybook 8 に対応した v4.3.0 がリリースされており、スムーズにバージョンアップができました。

@storybook/addons が依存関係に追加されている場合は、エラーになるので削除します。

argTypesRegex を削除し、ハンドラに fn() を指定

@storybook/addon-actions を使用する際、今までは argTypesRegex: "^on.*" を指定して onXXX() という関数を action arguments として自動設定するのが一般的でしたが、この方法が非推奨になり、代わりに @storybook/test から import した fn() を args にそれぞれ渡すことが推奨されています。

https://storybook.js.org/docs/essentials/actions

This is quite useful when your component has dozens (or hundreds) of methods and you do not want to manually apply the fn utility for each of those methods. However, this is not the recommended way of writing actions. That's because automatically inferred args are not available as spies in your play function. If you use argTypesRegex and your stories have play functions, you will need to also define args with the fn utility to test them in your play function.

fn() を使うことで play function でも自動でその関数をモックしてくれるようです。

またこれに付随した修正だと思われますが、 TypeScript を使用している場合、Props として Optional でない関数が定義されていても勝手に Optional にしてくれていましたがこの挙動がなくなったため、 fn() を渡さないとエラーになりました。

私のプロジェクトではそこまで数が多くなかったため手動で修正しましたが、規模のあるプロジェクトの場合はこれが一番大きな修正になると思います。

Webpack の Compiler 設定

@storybook/react-webpack5 に今まで含まれていた Babel のセットアップが標準で含まれなくなり、 Babel または SWC を使いたい場合別途設定が必要になりました。

https://storybook.js.org/docs/builders/webpack#compiler-support

例えば Babel を設定する場合、 @storybook/addon-webpack-compiler-babel を依存関係に追加した上で main.(js|ts)addons に追加する必要があります。

ドキュメントにあるように、

npx storybook@latest add @storybook/addon-webpack5-compiler-babel

コマンドを実行すると依存関係への追加と main.(js|ts) の修正の両方をやってくれます。[4]

私のプロジェクトでは monorepo 内の共通 UI ライブラリで React Native Web を使っているのですが、元々 .babelrc を設置していたため Babel を設定しました。[5]

*.stories.mdx の修正

過去に init コマンドで作成された Introduction.stories.mdx をそのまま置いていたところ Error: Invariant failed: No matching indexer found for /.../Introduction.stories.mdx というエラーが発生しました。

特に使っていなかったので削除してもよかったのですが、マイグレーションガイドに従って storybook migrate mdx-to-csf コマンドを使って *.stories.mdx ファイルを *.mdx ファイルに修正しました。

# Convert stories in MDX to CSF
npx storybook@latest migrate mdx-to-csf --glob "src/**/*.stories.mdx”

https://storybook.js.org/docs/migration-guide#storiesmdx-to-mdxcsf

Play function 再利用時の型修正

composeStories を使い Jest 等で play function を再利用するときの .play() TypeScript の型が Optional になったため .play?.() もしくは .play!() に変更する必要がありました。

const { Primary } = composeStories(stories)

// before
await Primary.play(...)

// after
await Primary.play?.(...) // if you don't care whether the play function exists
await Primary.play!(...) // if you want a runtime error when the play function does not exist

ただしマイグレーションガイドによると近日中に Story の play function の有無が型に反映されるようにすることを予定しているとのことなので、この改善が行われれば .play() に戻すことができるようになりそうです。

https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#type-change-in-composestories-api

There are plans to make the type of the play function be inferred based on your imported story's play function in a near future, so the types will be 100% accurate.

まとめ

ここまで Storybook 8 のアップデート内容について触れてきませんでしたが、

  • Chromatic と連携した新しい Visual Testing Addon
  • Next.js の React Server Component サポート
  • Vite 対応の改善

などを始めとした多くの新機能や改善が行われており、多方面で嬉しいリリースとなっています。

必ずしも常に最新版に追従するべきという訳ではないですが、いずれは避けて通れなくなる可能性が高いので、例えすぐにアップグレードしない場合でも対応内容をある程度は把握しておくといいでしょう。

脚注
  1. リリース日は、npm に公開されたのはもう少し前のようですが、Xの公式アカウントのアナウンスを基準とします。 ↩︎

  2. Storybook 7 へのアップグレードも最近行ったばかりでその記事も書いていたのですが、賞味期限切れになってしまいました... ↩︎

  3. プロジェクト構成については こちらのスライド も参照。 ↩︎

  4. 最初、 yarn add だけやって addons に追加していなかったため反映されず、途中でドキュメントが npx storybook add コマンドになっていることに気づきました。 ↩︎

  5. Next.js からも参照しているためおそらく SWC でも動かせると思うのですが、取り急ぎ動くことを優先しました。 ↩︎

GENDA

Discussion