はじめに
Storybookを用いてフロントエンドの開発を行うことはとても体験がよく重宝しています。そんなStorybookの最新バージョンである7.0のベータ版が昨夜(2022/12/8)リリースされました。
この記事ではVite×Reactに関係するStorybook 7.0の機能について解説を行います。
Storybookの7.0への移行ガイドはこちらになります。
この記事はBeta版での解説ですのでリリース時には異なる内容になっている可能性があります。
Viteを使ったStorybookの環境構築
storybookでvite環境を作るには一つのコマンドだけが必要です。以下のコマンドを入力すると最新バージョンの環境が手に入ります。
npx sb@latest init --builder=vite
これによって.storybook
フォルダが作成され、main.cjs
とpreview.cjs
とpreview-head.html
が生成されます。またサンプルとしてsrc
配下にstories
ディレクトリが生成され、ボタンなどのコンポーネントとstoryが準備されます。どの様なファイルが含まれていて、内容がどうなっているかはこの記事には大きく関係しないので自分で構築して確かめて下さい。
7.0と比較
先ほどのコマンドによって生成されたファイルを7.0のものと比較します。執筆当時の最新バージョンである6.5.14と最新のベータバージョンである7.0.0-beta.0比較を行います。最新のベータバージョンはnextを指定することで得られます。
npx sb@next init --builder=vite
変更は3点です。main.cjsと各storiesファイル、storybookのscriptsコマンドです。
main.cjs
6.5.14では以下のようになっています。
module.exports = {
"stories": [
"../src/**/*.stories.mdx",
"../src/**/*.stories.@(js|jsx|ts|tsx)"
],
"addons": [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-interactions"
],
"framework": "@storybook/react",
"core": {
"builder": "@storybook/builder-vite"
},
"features": {
"storyStoreV7": true
}
}
7.0.0-beta.0では以下のようになっています。pathは使っていないので以後考えないことにします(消しても良いと思います)。
const path = require('path');
module.exports = {
"stories": [
"../src/**/*.mdx",
"../src/**/*.stories.@(js|jsx|ts|tsx)"
],
"addons": [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-interactions"
],
"framework": {
"name": "@storybook/react-vite",
"options": {}
},
"docs": {
"docsPage": true
}
}
変更はこの部分です。
- "framework": "@storybook/react",
- "core": {
- "builder": "@storybook/builder-vite"
- },
- "features": {
- "storyStoreV7": true
- }
+ "framework": {
+ "name": "@storybook/react-vite",
+ "options": {}
+ },
+ "docs": {
+ "docsPage": true
+ }
フレームワークが@storybook/react
から@storybook/react-vite
になり、core
の設定が消えました。これはframworkにUIライブラリとbuilderを組み合わせた値を渡せるようになり、まとめて記述することになったからです。
次にfeatures
が消えました。7.0の機能を先取りする機能みたいなものなので、7.0になったら消えるのが当然のものです。
最後にdocs
が追加されています。7.0ではDocs周りの機能が大きく変わっています。これまではStoryを記述すれば自動的にDocsも記述されて、CanvasとDocsを切り替えることでDocsの確認をすることができました。
7.0ではDocsの自動生成がデフォルトではされなくなりました。従来通り記述させたい場合はdocsPage
を"automatic"
に設定することで自動的に生成されるようになります。さらに、画面上部で行うDocsとCanvasの切り替えではなくなりコンポーネントの切り替えと同じように切り替えるようになりました。
docsPage
をfalse
にすると完全にDocsが生成されなくなるので注意して下さい。デフォルトになったtrue
の時のDocsの生成方法はstoriesファイルの説明の時に行います。
stories
storyの書き方は大きく変わりました。CSF2の記法だったものからCSF3に移行しました。まずは見比べてみましょう。まずは6.5.14の書き方です。
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Button } from './Button';
export default {
title: 'Example/Button',
component: Button,
} as ComponentMeta<typeof Button>;
const Template: ComponentStory<typeof Button> = (args) => <Button {...args} />;
export const Primary = Template.bind({});
Primary.args = {
primary: true,
label: 'Button',
};
次に7.0.0-beta.0の書き方です。
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
const meta: Meta<typeof Button> = {
title: 'Example/Button',
component: Button,
};
export default meta;
export const Primary: StoryObj<typeof Button> = {
args: {
primary: true,
label: 'Button',
},
};
あまりにも変更が大きいですね。7.0.0-beta.0の方が記述が簡素になっていることがわかると思います。
まず、7.0ではComponentMetaやStory、ComponentStory、ComponentStoryFn、ComponentStoryObjが非推奨になってしまいました。それぞれMeta、StoryFn、StoryObjに置き換える必要があります(ComponentMeta=>Meta、Story=>StoryFn、ComponentStory=>StoryObj、ComponentStoryFn=StoryFn、ComponentStoryObj=StoryObj)。
次にmeta
のdefault exportの方法が変わりました。これは元の記法でも動きますので変更する必要はないです。私はasを使わない新記法が好みです。型はComponentMetaからMetaに変える必要があります。
最後にStoryの記法が大きく変わりました。TemplateのようにComponentStoryを別で定義する必要はなくなり、必要なオブジェクトを定義したStoryObj
をnamed exportするだけでStoryの定義が可能になりました。例ではargsだけをキーに持ってますが、play
やdecorators
などこれまで別々に宣言していたものが一つにまとめて宣言できるようになりました。
これらはCSF2からCSF3に移行するための変更ですので下のコマンドを用いてアップグレードできます。ぜひご利用ください。
npx sb@next migrate csf-2-to-3 --glob="**/*.stories.js"
main.cjs
の設定でdocsPage
をtrue
にした場合はStoryの設定ファイルでDocsの定義ができます。meta
を以下のようにすることでそのStoryのDocsを生成させることができます。各Storyで定義するのが億劫でこれまで通りを望んでいる場合はdocPage
を"automatic"
に変更して下さい。
const meta: Meta<typeof Button> = {
title: 'Example/Button',
component: Button,
tags: ['docsPage'],
};
コマンド
storybookではこれまでstart-storybook
、build-storybook
コマンドを用いて起動、ビルドを行っていました。package.jsonにはこの様に書かれていました。
{
"scripts": {
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook",
}
}
7.0ではこれらのコマンドが一つに統一されます。
{
"scripts": {
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
}
}
さらにNode17以降でStorybookを利用する際に必要だったNODE_OPTIONS
である--openssl-legacy-provider
を設定する必要がなくなりました。NODE_OPTIONS=--openssl-legacy-provider npm run storybook
とする手間がなくなったので大変助かります。
その他
他に関係ありそうな変更を紹介します。
ルートタグのidの変更
storybookのコンポーネント表示を開始するタグのidをrootからstorybook-rootに変更されました。button
のコンポーネントは下の様に変化しました。
<div id="root">
<button>Submmit</button>
</div>
<div id="storybook-root">
<button>Submmit</button>
</div>
これによってidの競合による動作不良の頻度が減少しました(storybook-rootをidに指定することはほとんどアプリではないので)。
IE11非対応
Viteも基本非対応ですが@vitejs/plugin-legacy
を使うなどして対応している場合もあるので書きました。storybookはこれまでIE11にも対応していましたが、IE11も含めレガシーバージョンブラウザへの対応をやめました。React18でもIE11の対応をやめているので今後も対応し続けるのがかなり難しくなってきた印象です。
Color Mode
どこにも書いてませんでが、7.0からOSのLight/Dark Modeを読み取って自動でModeを設定してくれるようになりました。
同じ環境でも7.0よりも前と後のもので比べると以下のようになります。
実装しているアプリケーションによってはColor Modeを実装しておらず白背景に表示することを前提としているためにコンストラストの関係でコンポーネントが見えにくくなることあります。そうした場合はpreview.cjs
のparameters
オブジェクトに下のように追加して下さい。表示されるコンポーネントの背景が白になるのでアプリケーションの表示通りに開発を行うことができます。
export const parameters = {
backgrounds: {
default: 'light'
},
};
ベータ版へのアップデート
これまでは新しく環境を作成してバージョンによる差分を紹介して比較してきました。しかし、多くのユーザーはすでに利用しているstorybookからのアップデートを行うことがほとんどです。アップデートを行う場合は以下のコマンドを入力します。
npx sb@next upgrade --prerelease
入力するとコマンドラインでファイルの更新についていくつか聞かれます。実行コマンドの書き換え、main.cjs
のframework
の書き換え、mdxを使っている場合はmd1からmd2への書き換え、Docsの自動生成のための設定(docsPage: 'automatic'
)を行なってくれます。
このコマンドによる変化はpackage.json
でstorybook類のバージョンアップとscriptsの書き換え、main.cjs
の書き換えを行なってくれます。書き換え後のmain.cjs
は以下の通りです。
module.exports = {
"stories": ["../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
"addons": ["@storybook/addon-links", "@storybook/addon-essentials", "@storybook/addon-interactions"],
"framework": {
name: "@storybook/react-vite",
options: {}
},
"core": {},
"features": {
"storyStoreV7": true
},
docs: {
docsPage: "automatic"
}
};
coreやfeaturesは意味をなしていないので消しても構いません。自動で色々設定してくれるのでとても助かります。
削除後はmigrate csf-2-to-3
などでstoriesファイルをCSF2からCSF3に移行すれば完了です。