🐾

Hygenを使用して対話形式でファイルを生成するのを試した

2023/02/01に公開

Hygenとは

hygenは、シンプルで、高速で、スケーラブルなコードジェネレータです。

https://www.hygen.io/

この記事でやること

Hygenを使用して、対話形式でファイルが生成されるようにします。
今回作成したいファイルと実際の対話の流れは以下の通りです。

💻 ・・・ 質問
🙋‍♂️ ・・・ 開発者

  • 対話の流れ
    💻 ? What is the directory name?
    🙋‍♂️ > Button
    💻 ? What is the component name?
    🙋‍♂️ > Button
    💻 ? Do you want to create a types.ts file? (y/N)
    🙋‍♂️ > y

  • 生成されるファイル
    src/components/ui/Button/Button.tsx
    src/components/ui/Button/Button.stories.tsx
    src/components/ui/Button/types.ts

必要な手順

  • Hygenをインストールする
  • Hygen設定ファイルの作成をする
  • 自動生成したいファイルの設定をする
  • package.jsonにhygenコマンドを追記する
  • コマンドを実行してみよう

Hygenをインストールする

まずはHygenをインストールしましょう

npm i -D hygen

Hygen設定ファイルの作成をする

Hygen設定ファイルを作成します。

touch .hygen.js
.hygen.js
module.exports = {
  templates: `${__dirname}/hygen`,
};

自動生成したいファイルの設定

自動生成したいファイルの設定を定義するファイルを格納するためのディレクトリを作成します。

mkdir -p hygen/component/create

hygen/component/create/ 配下にプロンプト(対話の流れ)と自動生成したいファイルの定義をしていきます。
※ファイルの内容はそれぞれ適宜好きなように変更してください

prompt.js
module.exports = [
  {
    message: 'What is the directory name?',
    name: 'directory_name',
    type: 'input',
    validate: (answer) => {
      if (answer !== '') {
        return true
      }
    },
  },
  {
    message: 'What is the component name?',
    name: 'component_name',
    type: 'input',
    validate: (answer) => {
      if (answer !== '') {
        return true
      }
    },
  },
  {
    message: 'Do you want to create a types.ts file?',
    name: 'should_create_types_file',
    type: 'confirm',
  },
]


component.tsx.t
---
to: src/components/ui/<%= directory_name %>/<%= component_name %>.tsx
unless_exists: true
---

type Props = {
  text?: string;
}

export const <%= component_name %> = ({text}: Props) => {
  return <div>{text}</div>;
};

component.stories.tsx.t
---
to: src/components/ui/<%= directory_name %>/<%= component_name %>.stories.tsx
unless_exists: true
---

import { ComponentStory, ComponentMeta } from '@storybook/react'
import { <%= component_name %> } from './index'

export default {
  title: 'Components/<%= component_name %>/<%= component_name %>',
  component: <%= component_name %>,
  argTypes: {
    backgroundColor: { control: 'color' },
  },
} as ComponentMeta<typeof <%= component_name %>>

const Template: ComponentStory<typeof <%= component_name %>> = (args) => (
  <<%= component_name %> {...args} />
)

types.ts.t
---
to: "<%= should_create_types_file ? `src/components/ui/${directory_name}/types.ts` : null %>"
unless_exists: true
---

ファイルの構成要素

ファイル上部のコードフェンス(---)で書かれている部分であるフロントマター、実際に生成されるコードの部分であるテンプレートボディで構成されます。

  • フロントマター
    • ファイル上部の[--- hoge ---]で書かれている部分のこと
    • メタデータを定義する
  • テンプレートボディ
    • 実際に生成されるコードの部分のこと
    • ejsというテンプレートエンジンを使用して記述します

フロントマターで扱えるメタ情報・ejsについては以下を参照してください。
https://www.hygen.io/docs/templates#all-frontmatter-properties
https://ejs.co/

条件付きレンダリング

types.ts.tでは条件付きレンダリングされるようにしています。to: に対してnullを指定するとそのテンプレートの出力をスキップできます。
"Do you want to create a types.ts file?"の質問に対して「y」だと新規にファイルを作成し、「N」だと作成しないようにしています。

package.jsonにhygenコマンドを追記する

package.json
"create:component": "hygen component create"

コマンドを実行してみよう

npm run create:component

? What is the directory name? 
> Button
? What is the component name?
> Button

Loaded templates: hygen
       added: src/components/ui/Button/Button.stories.tsx
       added: src/components/ui/Button/Button.tsx

ファイルが作成されました🎉

参考にさせていただいた記事

https://zenn.dev/takepepe/articles/hygen-template-generator

最後に

内容は気まぐれで随時更新します。
間違っているところがあればコメントで教えていただけますと幸いです🙇‍♂️

Discussion