この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
オハコンバンニチハ、モバイルアプリサービス部の清田です。
UI Component 管理ツールの Storybook がメジャーバージョンアップし バージョン5 になりましたー!パチパチ。 今回は、Storybook の魅力と導入についてご紹介できればと思います。
Storybookとは?
Storybookは、UI Component 管理・開発環境を提供するオープンソースのツールです。
主な用途としては以下な感じです。
- デザインスタイルガイド、
- コンポーネントの挙動確認、
- UIコンポーネント仕様、画面仕様の確認など
Webフロントエンド界隈で主要なフレームワークに対応しているので、ご利用できる範囲も広い印象です。
- React
- Vue
- Angular
そして、サンフランシスコに拠点を置く、Chroma Software 社がツールの主な運営のもと、 世界中の有志のコントリビューターさん達によって維持されているみたいです。
ちなみにツールのデザインを担当されたのが、Dominic Nguyen(@domyen)さんとのこと。
ありがたやー。
おしながき
今回はお仕事でお世話になっている React x TypeScript 構成を想定し、Storybook環境構築してみたいと思います。
実行環境について
今回の導入に際して、環境情報を以下に記載します。
- OS: macOS Mojave v10.14 ++
- NodeJS: v10.13.0 ++
- npm: v6.4.1 ++
- yarn: v1.12.3 ++
ディレクトリ構成
ディレクトリ構成について、デファクトな create-react-app
でもいいのですが、今回は自分のお好みの構成で構築できればなと。 今回はこんな感じになっています。
┣ internals
┃ ┣ storybook/
┃ ┃ ┣ addons.js
┃ ┃ ┣ config.js
┃ ┃ ┗ webpack.config.js
┃ ┗ tsconfig/
┃ ┗ tsconfig.storybook.json
┣ src
┃ ┗ Example/
┃ ┗ index.stories.tsx
┣ .babelrc
┗ package.json
パッケージのインストール
それではStorybookを利用するための環境を構築していこうと思います。
以下コマンドから、package.json
を作成します。
yarn init
続いて、各パッケージをインストールしていきます。
React
UIコンポーネント用のフレームワークとして利用します。
yarn add react react-dom
yarn add -D @types/react @types/react-dom
Typescript
開発言語はTypescriptを利用します。
yarn add -D typescript ts-loader
Storybook & path
本題のstorybook関連のパッケージをインストールします。 storybookは各ライブラリ向けのパッケージを用意してくれているので今回はReact用のパッケージを利用します。
yarn add -D @storybook/react \
@types/storybook__react \
react-docgen-typescript-webpack-plugin \
path
ここまでで大体のパッケージはそろったのですが、 @storybook/react
追加後、以下のワーニングがでるのでbabel関連のパッケージもインストールしておきます。
warning " > @storybook/react@5.0.8" has unmet peer dependency "babel-loader@^7.0.0 || ^8.0.0".
warning "@storybook/react > @babel/plugin-transform-react-constant-elements@7.2.0" has unmet peer dependency "@babel/core@^7.0.0-0".
...
Babel
yarn add -D @babel/core \
@babel/preset-env \
babel-loader
設定ファイルの作成
パッケージのインストールが済んだので、各設定ファイルを作成していこうと思います。
.babelrc
今回は直接関係ないですが、以下の設定を定義します。
{
"presets": ["@babel/env", "@babel/react"]
}
webpack
Storybookは内部でwebpackを利用しています、その設定ファイルを定義します。
# internals/storybook/webpack.config.js
// ファイル指定関連
const fs = require('fs')
const path = require('path')
// docgen関連パッケージ読み込み
const TSDocgenPlugin = require('react-docgen-typescript-webpack-plugin')
// ディレクトリ指定用関数
const appDirectory = fs.realpathSync(process.cwd())
const resolveApp = relativePath => path.resolve(appDirectory, relativePath)
module.exports = {
module: {
rules: [
{
test: /\.(ts|tsx)$/,
loader: 'ts-loader',
exclude: /node_modules/,
include: resolveApp('src'),
options: {
configFile: `${resolveApp(
'internals/tsconfig'
)}/tsconfig.storybook.json`,
},
},
],
},
resolve: {
extensions: ['.ts', '.tsx'],
},
plugins: [new TSDocgenPlugin()],
}
tsconfig
今回のtsconfig設定情報はStorybook公式サイトから拝借してみました。
# internals/tsconfig/tsconfig.storybook.json
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"lib": ["es5", "es6", "es7", "es2017", "dom"],
"sourceMap": true,
"allowJs": false,
"jsx": "react",
"moduleResolution": "node",
"forceConsistentCasingInFileNames": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": true,
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"noUnusedLocals": true,
"declaration": true,
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true
},
"include": ["../../src/**/*"],
"exclude": ["../../node_modules"]
}
config.js
Storybookの設定情報を以下のファイルに記載します。
今回は指定した .stories.tsx
拡張子を取得する設定を記述しています。
# internals/storybook/config.js
import { configure } from "@storybook/react";
const req = require.context("../../src", true, /.stories.(ts|tsx)$/);
function loadStories() {
req.keys().forEach(filename => req(filename));
}
configure(loadStories, module);
package.json
最後にpackage.json側に実行コマンドを定義します。
指定オプション
- -p
ポート番号の指定
- -c
storybookの設定ファイル先指定
# package.json
{
...
"scripts": {
"storybook": "start-storybook -p 9001 -c ./internals/storybook",
},
...
}
Storybookの実行
最低限の環境設定ができたのでStorybookを起動してみたいと思います。
以下コマンドから正常に起動できると、http://localhost:9001/
からアクセスできるようになります。
yarn storybook
...
╭─────────────────────────────────────────────────╮
│ │
│ Storybook 5.0.8 started │
│ 5.98 s for manager and 7.12 s for preview │
│ │
│ Local: http://localhost:9001/ │
│ On your network: http://192.168.0.5:9001/ │
│ │
╰─────────────────────────────────────────────────╯
現時点では表示するコンポーネントを定義していないので、以下画面が表示すれば成功です。
Storybook 定義ファイル作成
Storybookを構成する定義ファイルを作成してみたいと思います。
src
ディレクトリー配下に .stories.tsx
拡張子のファイルを作成します。
# src/Example/index.stories.tsx
import * as React from "react";
import { storiesOf } from "@storybook/react";
storiesOf("Example", module).add("List item", () =>
<div>Hello :-)</div>
);
- (1) storiesOfメソッドの引数にコンポーネントディレクトリの名称を指定
- (2) addメソッドの第1引数にコンポーネントサブディレクトリの名称を指定
- (3) addメソッドの第2引数に描画するコンポーネントを指定
Storybookの構成
Storybookでコンポーネントを描画するところまではできました。 それでは、Storybookの画面構成についてかるく触れればと思います。
- Aエリア
- Storybook内で定義してある各コンポーネント間を遷移するナビゲーションになります。
- Bエリア:
- Storybook内のメインであるUIコンポーネントを描画するエリアになります。
- Cエリア:
- 今回はふれませんでしたが、StorybookはAddonといった拡張機能が描画されるエリアになります。
ナビゲーションエリアのツール紹介
以下の箇所を選択すると、Storybookのショートカットを確認できます。
以下の箇所からUIコンポーネントのキーワード検索が可能です。
コンポーネント描画エリアのツール紹介
以下の各ボタンにて表示系の操作が行えます。
- A: 拡大表示
- B: 縮小表示
- C: 拡大・縮小を初期表示
- D: グリッド表示
- E: 全画面表示
- F: 別画面表示
アドオンエリア
Storybookを有効的に使うためにはAddon機能は必要不可欠であったりします。 ちょっと今回はアドオン機能についての話しが長くなってしまうため次回アドオン機能の利用方法等ご紹介できればと思います。
まとめ
Storybookの環境構築についてご紹介いたしました。 昨年からメジャーバージョンが続いており活発に開発されている印象です。もし開発中のプロダクトでUIコンポーネントの管理に課題を感じている際はご検討してみてはいかがでしょうか?
おまけ Storybook Docs の紹介
自分のチームではStorbookをUIコンポーネントのデザインガイドラインや画面仕様的なドキュメンテーションに重きを置いた用途で利用を進めているのですが、つい先日 Storybook Docs なるアドオンがアナウンスされました。 まだ利用はできないのですが、MDX(Markdown中にJSXを埋め込めちゃうやつ)がサポートしてくれてるとか要チェックなアドオンです。