TypeScriptのReactプロジェクトでreact-styleguidistを使う
2018-03-14

TypeScriptのReactプロジェクトでreact-styleguidistを使う

今回は、TypeScriptのReactプロジェクトとreact-styleguidistを一緒に使う方法についての紹介です。

紹介する内容は、こちらのGithubで見ることができます。

はじめに

react-styleguidistとは、「style guide」と呼ばれるドキュメントツールの一種です。

最近は、小さなReactコンポーネントを積み重ねて巨大なアプリケーションを構築していくのですが、どんなコンポーネントがあるかを俯瞰的見るために、このようなツールを使います。

こちらで公式のサンプルを見ることができます。

個人的には、「コンポーネントカタログ」と言った方がバックエンドの人も理解してくれるので、こちらの呼び方をする方が多い。

基本セットアップ

まず、react-styleguidistをインストールします。

npm install --save-dev react-styleguidist

つぎにpackage.jsonscriptsの部分にタスクを追加していきます。

{
  ...
  "scripts": {
    "styleguide": "styleguidist server",
    "styleguide:build": "styleguidist build"
  }
  ...
}

最後にstyleguide.config.jsを作成して、TypeScriptのプロジェクトで動かすための設定を追加します。

module.exports = {
  components: "src/shared/components/**/*.{ts,tsx}",
  webpackConfig: Object.assign({}, require("./webpack.config"), {}),
  propsParser: require("react-docgen-typescript").parse,
};

細かい内容はこちらです。

  • components: コンポーネントとして扱うファイルをglob形式で指定します。
  • webpackConfig: react-styleguidistはTypeScriptのコンパイルができないので、Webpackの設定ファイルを指定します。
  • propsParser: TypeScriptのinterfaceなどのProps情報をメタデータに変換するためのカスタムPaserです。

以上で、基本セットアップは完了しました。

コードのサンプルや使用例は、コンポーネントと同じディレクトリにREADME.mdを作成します。

// README.md

ここに説明

```
<Lovely />
```

そのあとにnpm run styleguideをすると、スタイルガイドが見れるようになります。

Reduxと一緒に使う

Reduxなどのサードパーティ製のライブラリと一緒に使う場合は、既存のスタイルガイドのrootコンポーネントを置き換える必要があります。
今回は割と需要がありそうな国際化ライブラリreact-intl-reduxを使ってみました。

Wrapper.tsxという名前のコンポーネントを作成して、これで置き換えます。

// src/styleguide/Wrapper.tsx

...

import { Provider } from "react-intl-redux";
import { addLocaleData } from "react-intl";
import * as jaLocale from "react-intl/locale-data/ja";

// add japanese localisation data
addLocaleData([...jaLocale]);

... (Redux storeの準備)

// デフォルトの言語設定
store.dispatch(langSwitchAction("ja"));

export default class Wrapper extends React.Component<{}, {}> {
  render() {
    return (
      <Provider store={store}>
        {this.props.children}
      </Provider>
    );
  }
}

ReduxのStoreの準備は、プロジェクトのエントリポイントのファイル(通常はentry.tsxとかindex.tsx)にあると思うので、そのまま使えると思います。
いろいろ割愛しているので、詳細はこちらのコードを見てください。

作成したコンポーネントをstyleguide.config.jsに設定します。

module.exports = {
  ...
+  styleguideComponents: {
+    Wrapper: __dirname + "/src/styleguide/Wrapper.tsx",
+  },
  ...
};

これでサードパーティ製のライブラリと一緒に使うことができるようになりました。

Connectコンポーネントを使うための工夫

この工夫は必要ない人もいると思います。ただカスタマイズが必要になった場合に必要な知識なので、頭の片隅にでも覚えておくといいと思います。

プロダクトの構成次第ですが、自分の場合はコンポーネントに関連するファイル一式を同じフォルダに管理しています。

Lovely
  Lovely.tsx
  Lovely.connect.tsx
  Lovely.scss
  Lovely.spec.tsx
  README.md

このような構成をとった場合、(styleguide.config.jscomponentsの設定次第ではありますが)Lovely.tsxLovely.connect.tsxの2つがスタイルガイド上に登場してしまいます。

そのため、componentsプロパティをもう少しカスタマイズする必要が出てきます。
componentsプロパティは基本的にnode-globで対象となったコンポーネントのリストがあればいいので、これに関数を渡してカスタマイズします。

module.exports = {
  ...
  components: () => {
    return glob.sync("src/shared/components/**/*.{ts,tsx}").filter(file => {
      // Take only connect component if exists, ignore others.
      if (file.match(/connect.tsx$/)) {
        return true
      } else {
        const pathObject = path.parse(file);
        pathObject.ext = `.connect${pathObject.ext}`
        const { root, dir, ext, name } = pathObject;
        return !fs.existsSync(path.format({ root, dir, ext, name }));
      }
    });
  },
  ...
};

同じフォルダにconnect.tsxがあったら、これをスタイルガイドのコンポーネントとして使うだけのコードです。
ご自身の環境に合わせてさらにカスタマイズすることもできます。

最後にREADME.mdで使うコンポーネントを調整する必要があります。

README.mdのExampleプロックの中では、requireでモジュールをロードして使えるので、次のようにConnectコンポーネントを直接呼び出して利用します。

// README.md

```
const FormattedMessage = require("react-intl").FormattedMessage;
const LangSwitch = require("./LangSwitch.connect").default;
<div>
  <LangSwitch />
  <p><FormattedMessage id={"greeting"} /></p>
</div>
```

他にもできることがあるので、詳しい説明は公式ドキュメントを見てください。

まとめ

TypeScriptのReactプロジェクトとreact-styleguidistを一緒に使う方法についての紹介でした。

(余談)
すこし前までは、create-react-appで作成したアプリケーションはwebpack.config.jsを取り出す手段がなかったので、仕方なくejectしていまいたが、今は必要ないようです。素晴らしい。