🦥

Plopを使ってStorybookのコード生成を自動化してみた

2025/03/10に公開

導入経緯

Storybookを使ってコンポーネントを管理する際、各コンポーネントごとに個別にstoryファイルを作成する必要があります。この作業は一見単純に見えますが、コンポーネントの数が増えるにつれて、ディレクトリ名やインポートファイル名を都度変更する手間が発生します。そこで、開発の生産性を向上させるために「Plop」というジェネレーターライブラリを導入し、storyファイルの自動生成を実現しました。本記事では、Plopを導入して、どのようにstoryファイルを自動化するか、その設定方法と実行手順を紹介します。

Plopとは?

Javascriptのジェネレーターライブラリで、開発者が手動で繰り返し行う作業を自動化し、コードやファイルの生成を効率化することができます。特に、テンプレートを基にファイルを自動的に生成する機能を提供しており、開発作業をスピードアップできます。
https://plopjs.com/

設定方法

Plopを使って自動生成を行うためには、以下の手順で設定を行います。

1. インストール

npm install plop

2. 必要なファイルの設定

自動生成に必要な2つのファイルを設定します。

plopfile.mjs

plopfile.mjsはPlopでコードを自動生成するための設定ファイルです。
このファイルで、ユーザーから入力を受け取るための質問(プロンプト)や、生成するファイルのパス、内容を指定します。

以下は、コンポーネントごとのstoryファイルを生成するための設定例です。

generators/plopfile.mjs

export default function (plop) {
  // ここで、ジェネレーターの定義を行います
  plop.setGenerator('storybook', {
    description: 'Generate Storybook story file',
    prompts: [
      {
        type: 'input', // ユーザーにテキスト入力を促す
        name: 'path', // 入力された内容を`path`として保存
        message: 'コンポーネントのディレクトリ名を入力してください(例:components/Atoms)',
      },
      {
        type: 'input',
        name: 'componentName', // 入力された内容を`componentName`として保存
        message: 'コンポーネント名を入力してください(例:Button)',
      },
    ],
    actions: [
      {
        type: 'add', // 新しいファイルを生成するアクション
        path: 'src/{{path}}/{{componentName}}.stories.js', // 生成するファイルのパス
        templateFile: 'plop-templates/storybook.hbs', // 使用するテンプレートファイル(後述)
      },
    ],
  });
}


hbsファイル

hbsファイル(.hbs)は、テンプレートエンジン「Handlebars」で使用されるテンプレートファイルです。Handlebarsは、Javascriptベースのテンプレートエンジンで、HTMLやその他のテキストベースのドキュメントを動的に生成するために使用されます。マスタッシュ記法{{ }}を使用して、データをテンプレートに埋め込むことができます。

plopfile.mjsで指定された変数componentNamepathへの入力値を基に、テンプレートが生成される仕組みです。

storybook.hbs
import {{componentName}} from 'src/{{path}}/{{componentName}}';

export default {
  title: '{{path}}/{{componentName}}',
  component: {{componentName}},
};

export const Default = {
  render: (args) => ({
    components: { {{ componentName }} },
    setup() {
      return { args };
    },
    template: "<{{componentName}} v-bind='args' />",
  }),
  args: {
    // propsで受け取る値を設定してください
  },
};

3. package.jsonにスクリプトを追加

最後にPlopを簡単に実行できるよう、package.jsonにスクリプトを追加します。

"scripts" : {
    "plop" : "plop --plopfile ./generators/plopfile.mjs"
}

実行

設定が完了したので、実際にPlopを使っていきます。

1. スクリプトの実行

npm run plop

2. 対象コンポーネントを指定

スクリプトを実行すると、下記のようにplopfile.mjs内で設定した1つ目のプロンプトが表示されます。

今回は、components/AtomsディレクトリにあるButton.vueのstoryファイルを自動生成したいので、components/Atomsと入力します。
1つ目のプロンプトに答えると、続いて2つ目も表示されるので同様に、Buttonと入力します。

3. ファイルが作成される

ユーザーが入力した内容に基づき、指定したテンプレートファイルに従って、Storybookのstoryファイルが自動で作成されます。以下は、Buttonコンポーネントのstoryファイルの例です。
また、作成されたstoryファイルのパスはplopfile.mjsのactionsで指定したpathになります。

src/components/Atoms/Button.stories.js
import Button from 'src/components/Atoms/Button';

export default {
  title: 'components/Atoms/Button',
  component: Button,
};

export const Default = {
  render: (args) => ({
    components: { Button },
    setup() {
      return { args };
    },
    template: "<Button v-bind='args' />",
  }),
  args: {
    // propsで受け取る値を設定してください
  },
};

まとめ

Plopを導入することで、Storybookのstoryファイルを手動で繰り返し作成する手間を大幅に削減することができました。これにより、コンポーネントごとのstoryファイル作成の効率化が進み、開発者の作業負担を軽減することが可能となりました。

複数のコンポーネントに対して同じテンプレートを適用できるため、一貫性のあるコードを素早く作成することができるのも嬉しい点です。

フロントエンドに限らず活用できるツールだと思いますので、参考になれば嬉しいです!

Spectee Developers Blog

Discussion