りゅうじの学習blog

学習したことをアウトプットしていきます。

6/21 コンポーネント駆動開発、簡易な導入手順まとめ

使うライブラリ・パッケージと概要

  • React, TypeScript, Storybook: ReactはJavaScriptライブラリであり、ユーザーインターフェイスの構築を容易にします。TypeScriptはJavaScriptのスーパーセットで、型安全性を提供し、バグを早期に発見し、コードのリーダブル性と保守性を向上します。StorybookはUIコンポーネントの開発とドキュメンテーションを支援するツールです。Storybookを使用すると、各コンポーネントの異なる状態を視覚的に確認することができます。
  • Jest: JestはJavaScriptのテストフレームワークで、Reactコンポーネントのテストに特に適しています。Jestはユニットテスト結合テストの両方をサポートしており、モック関数やスナップショットテストなどの機能も提供しています。
  • Plop: Plopはボイラープレートコードを生成するためのツールです。あらかじめ定義したテンプレートを元に新しいコンポーネントやテストの雛形を簡単に生成することができます。
  • MSW (Mock Service Worker): MSWはブラウザとNode.jsで動作するモック/スパイライブラリです。MSWはネットワークリクエストを補足し、定義したモックレスポンスを返します。これにより、APIの実装が未完成でもフロントエンドの開発やテストを進めることができます。

導入手順

React TypeScriptプロジェクトの作成

npx create-react-app my-app --template typescript

TypeScriptのオプションをつけることで、作成時からTypeScriptの初期設定やファイル名になります。

Storybookのインストール

npx sb init

.storybook ディレクトリが作成される。

また、既存のデフォルトのストーリーは src/stories ディレクトリ内に格納される。

Jestのインストール:

Jestは create-react-app にデフォルトで含まれていますが、追加の設定や型定義が必要な場合は次のコマンドを実行Jestは create-react-app にデフォルトで含まれていますが、追加の設定や型定義が必要な場合は次のコマンドを実行

Plopのインストールと設定:

npm i -D plop

プロジェクトのルートディレクトリに plopfile.js ファイルを作成

touch plopfile.js

plopfile.js

module.exports = function (plop) {
    // コンポーネントジェネレータを作成します
    plop.setGenerator('component', {
        description: 'Create a component',
        prompts: [{
            type: 'input',
            name: 'name',
            message: 'What is your component name?'
        }],
        actions: [
            {
                type: 'add',
                path: 'src/components/{{pascalCase name}}/{{pascalCase name}}.tsx',
                templateFile: 'plop-templates/Component.tsx.hbs'
            },
            {
                type: 'add',
                path: 'src/components/{{pascalCase name}}/{{pascalCase name}}.stories.tsx',
                templateFile: 'plop-templates/Component.stories.tsx.hbs'
            }
        ]
    });
};
  • Plopの設定ファイルで、このファイルによってPlopがどのように動作すべきかを定義
    • このファイル内で、生成されるファイルのタイプや名前、テンプレートとなるファイルへのパス、プロンプトの質問などを設定している

plop-templatesというディレクトリをプロジェクトのルートに作成

その中にテンプレートとなるComponent.tsx.hbsComponent.stories.tsx.hbsという2つのファイルを作成

これらの.hbsファイルはHandlebarsテンプレートと呼ばれ、特定の箇所を置換して新しいファイルを生成するために使用される

基本的な例

Component.tsx.hbs

import React from 'react';

export interface {{pascalCase name}}Props {

}

export const {{pascalCase name}}: React.FC<{{pascalCase name}}Props> = (props) => {
    return (
        <div>
            {/* Implement your component here */}
        </div>
    );
}

Component.stories.tsx.hbs

import React from 'react';
import { {{pascalCase name}}, {{pascalCase name}}Props } from './{{pascalCase name}}';

export default {
    title: 'Example/{{pascalCase name}}',
    component: {{pascalCase name}},
};

const Template: React.VFC<{{pascalCase name}}Props> = (args) => <{{pascalCase name}} {...args} />;

export const Primary = Template.bind({});
Primary.args = {
    /* Fill in your default args here */
};

npx plop componentコマンドを実行すると、ファイル名を聞かれるので、例としてbuttonと答えたとすると、Button.tsxButton.stories.tsxsrc/components/Button/ディレクトリに作成される

ストーリーブックのテスト設定

ストーリーブックのテストには、@storybook/addon-storyshotsを使用する。これをインストールして、自動的にStorybookのスナップショットテストを作成できる。

npm install --save-dev @storybook/addon-storyshots react-test-renderer

srcディレクトリにstoryshots.test.jsという新しいファイルを作成

touch src/storyshots.test.js

storyshots.test.jsファイルに以下の内容を追加

import initStoryshots from '@storybook/addon-storyshots';

initStoryshots();

この設定により、Jestがテストを行うときにStorybookの各ストーリーのスナップショットテストを自動的に行う

テストの実行:

npm test
  • start test などは、package.jsonのscriptsに書かれていて、runをつけなくてもいい
  • このコマンドでjestのテストが走ります

storybook起動

npm run storybook
  • このコマンドをするとブラウザにstorybookが立ち上がるので、現状のstorybook(今回の例だとbuttonコンポーネント)が反映される

mswの設定:

npm install msw

mswを設定します。以下のコードをsrc/mocks/handlers.jsに追加します。

import { rest } from 'msw'

export const handlers = [
  rest.post('https://example.com/api/submit', (req, res, ctx) => {
    return res(ctx.json({ message: 'Success' }))
  }),
]

このハンドラをテスト環境で使用できるように設定します。以下のコードをsrc/mocks/browser.jsに追加します。

import { setupWorker } from 'msw'
import { handlers } from './handlers'

export const worker = setupWorker(...handlers)

テストのセットアップとクリーンアップでmswサーバーを起動と停止します。以下のコードをsrc/setupTests.jsに追加します。

import { server } from './mocks/server.js'

beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())

これでmswがテストで利用可能になりました。

基本的なコード例

import React from 'react'
import { render, fireEvent, waitFor } from '@testing-library/react'
import { rest } from 'msw'
import { server } from './mocks/server'
import Button from './Button'

test('submits the form when the button is clicked', async () => {
  server.use(
    rest.post('https://example.com/api/submit', (req, res, ctx) => {
      return res(ctx.json({ message: 'Success' }))
    })
  )

  const mockOnClick = jest.fn()
  const { getByText } = render(<Button

コメント

実務でフロントエンドをCDDで開発することになったので、一回自分で小さく動かしてみるために、設定方法を簡単にまとめました。