モノクロタイム

I'm from the future!

rollup+React+Storybook+TypeScriptで自作コンポーネントライブラリを作る

こんにちは、れいじです

ハッカソンに参加する時や、自作サービスをを開発する時に簡単に使えるサークル固有のコンポーネントキットがあったらいいな~と思って作ってみることにしました。

既にnpmには登録されていて、一応OSS開発者(笑)です。使う人自分しかいないけど。

www.npmjs.com

掲題の構成、かなり手間取ったのでメモを残しておきます。超だるい。

githubリポジトリはこちら。

github.com

Storybook はGithub Pagesで公開中です。

reiji1020.github.io

基本的には以下の記事を参考にしています。

zenn.dev

ディレクトリ構成は以下の通り。詳しくはgithubリポジトリを見て下さい。

➜  ccl-component-kit git:(main) tree -a -I "\.DS_Store|\.git|node_modules|vendor\/bundle" -N
.
├── .babelrc
├── .gitignore
├── .idea
│   ├── .gitignore
│   ├── ccl-component-kit.iml
│   ├── markdown.xml
│   ├── modules.xml
│   ├── vcs.xml
│   └── workspace.xml
├── .npmignore
├── .storybook
│   ├── main.js
│   └── preview.js
├── LICENSE
├── README.md
├── dist
│   └── index.cjs.js
├── package.json
├── rollup.config-1666438016873.cjs
├── rollup.config.js
├── src
│   ├── index.ts
│   └── stories
│       ├── Header.stories.jsx
│       ├── Header.tsx
│       ├── Introduction.stories.mdx
│       ├── assets
│       │   └── CCL_logo.svg
│       └── header.css
├── storybook-static(ディレクトリ内はデプロイ用ファイルなので割愛)
├── tsconfig.json
├── yarn-error.log
└── yarn.lock

以下の条件で環境構築しています。

  • yarn 1.22.19

  • node 16.16.0

  • wslによるzsh環境を使用

Reactライブラリを導入する

基本的にStorybook を導入するにはサンプルコンポーネント入りのパッケージを導入するのが手っ取り早いので、これを導入します。

上記のブログだと以下のコマンドでStorybook を導入後すぐにStorybook の起動が確認できますが、Reactを導入しないと動かないのでyarn addで導入しておきます。

npx -p @storybook/cli sb init --type react

これに加えて、以下を導入

yarn add -D react react-dom @types/react @types/react-dom

typesのパッケージを導入するのは、コンポーネントは基本的にTypeScriptで制作・管理していきたいと考えているからです。

これでStorybook の起動自体はできるようになります。

TypeScriptに対応させる

これが非常に厄介です

まずはtypescriptを導入します。

yarn add -D typescript

次にrollupのtypescript系アドオンを導入します。

yarn add -D @rollup/plugin-typescript

TypeScriptを導入したのでtsconfig.jsonを置きます。基本的にrollup側でよしなにやってほしいので、ごちゃっと変換しないようにしています。

{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ES6",
    "strict": true,
    "esModuleInterop": true,
    "sourceMap": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "jsx": "react"
  },
  "include": ["src"]
}

rollup.config.js側ではtypescriptアドオンを利用してTypeScriptのコードを変換できるようにしています。 解説どころとしてはacorn-jsxですが、storiesなどを一旦jsxのまま扱っているので仕方なく導入しています。現時点でヘッダにプロパティを持たせる予定はないのですが、一旦デプロイ重視でそのまま置いているので、jsxファイルをrollupでビルドできるようにしています。(後々消してOKなやつだと認識しています)

typescriptの項目も同じで、jsxファイルを読み込めるようにcompilerOptionを設定しています。このあたりを設定しないと動かない筈。

import styles from "rollup-plugin-styles";
import babel from '@rollup/plugin-babel';
import sourcemaps from 'rollup-plugin-sourcemaps';
import del from 'rollup-plugin-delete';
import commonjs from '@rollup/plugin-commonjs';
import nodeResolve from '@rollup/plugin-node-resolve';
import jsx from 'acorn-jsx';
import typescript from '@rollup/plugin-typescript';

const autoprefixer = require('autoprefixer');
const production = !process.env.ROLLUP_WATCH;

const conf = {
    input: "src/index.ts",
    output: {
        sourcemap: !production,
        file: "dist/index.cjs.js",
        format: "cjs",
        exports: "auto"
    },
    // this externelizes react to prevent rollup from compiling it
    external: ["react", /@babel\/runtime/],
    acornInjectPlugins: [jsx()], // jsxファイルの読み込みに必要
    plugins: [
        // these are babel comfigurations
        babel({
            exclude: 'node_modules/**',
            plugins: ['@babel/transform-runtime'],
            babelHelpers: 'runtime'
        }),
        // this adds sourcemaps
        sourcemaps(),
        del({targets:'dist/*'}),
        // this adds support for styles
        styles({
            postcss: {
                plugins: [
                    autoprefixer()
                ]
            }
        }),
        nodeResolve({
            preferBuiltins: false
        }),
        commonjs(),
        typescript({
            compilerOptions: {
                jsx: 'preserve'
            },
            sourceMap: false
        })
    ]
}

export default conf;

package.jsonのコマンドについて

rollupのビルドコマンドについて、現時点では rollup -c だけでは動かなくなっています。

[!] RollupError: Node tried to load your configuration as an ES module even though it is likely CommonJS.
To resolve this, change the extension of your configuration to ".cjs" or pass the "--bundleConfigAsCjs" flag.

↑こんな感じのエラーメッセージが出ます。なので、ビルドコマンドは以下で登録しておくのが良さそうです。

    "scripts": {
        "build": "rollup --config --bundleConfigAsCjs",
  …
    },

おまけ:GithubPagesでStorybook のコンポーネントドキュメントを公開する

整備されているかどうかは別として、コンポーネントドキュメントがあるととても便利です。

以下のコマンドでgh-pagesのツールを導入します。

yarn add -D gh-pages

導入できたら、以下のコマンドでデプロイ用のStorybook ディレクトリを生成します。このディレクトリはバージョン管理する必要がないので、.gitignoreに登録しておきます。

yarn buld-storybook

storybook-staticディレクトリが無事に生成できたら、GithubPagesに登録しましょう。以下のようにpackage.jsonへコマンドを定義しておくと便利です。

"gh-deploy": "gh-pages -d storybook-static"
yarn gh-deploy

デプロイが成功すると、リポジトリのGithubPagesに自動的に登録されるため誰でも最新のドキュメントを参照することができるようになります。

まとめ

何やっても環境構築だけで一日溶かすの本当につらいですね。WSL2だとStorybook のホットリロードが効かないのも地味にしんどいです。

ただもう環境を変えることはないはずなので、あとはそんなにつらいポイントはないと信じたい…