7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Next.jsで開発中によく思うんですが、毎度コンポーネントを新しく作るたびに.test.tsx.stories.tsxを作るのとても面倒ですよね。
css moduleを採用していると、さらにそこに追加で.module.cssをドンです。もう手間でしかありません。

これまで、この辺りので楽をするためにはvscodeのユーザースニペットを活用して居たんですが、それよりももっと便利なものを最近知ったので紹介します。それがhygenです。

hygen とはなんぞや

hygenとは、ざっくり言うとテンプレートエンジンです。
事前に作成しておいたテンプレートとなるファイルと、生成時に入力した文字列を用いて任意のファイルを作成します。

具体的にどんなことができるかと言うとこんな感じです。

image.png

任意の文字列入力だけではなく、選択肢の中から選ばせることもできます。
例えば、上記のatomsは以下のように選択肢の中から選択させています。

image.png

以前はこの辺りの操作をするために、該当のディレクトリにcdしてtouchしてcodeで開いてスニペット開いてなんてやっていたので、それらがコマンド一発でできるようになり非常に便利になりました。

では、実際に手を動かしてhygenを使えるようにしていきます。

hygenを動かしてみる

環境

node: v18.12.1

インストール

npm等のnodejsパッケージマネージャかhomebrewからインストールできます。
今回記事はmacで書いているのでhomebrewからインストールできるのですが、npmから落とせるならそちらが良いので今回はpnpmを使用します。
npmでも落とせますがpnpmを使います。pnpmはいいぞ。

pnpm i -D hygen

インストールできたらinitの実行
実行すると、_templateディレクトリが作成されます。
今後、テンプレートとなるファイルなどはこちらに配置します。

pnpm hygen init self

作成されたディレクトリの中身はこんな感じです。

_templates/
├── generator
│   ├── help
│   │   └── index.ejs.t
│   ├── new
│   │   └── hello.ejs.t
│   └── with-prompt
│       ├── hello.ejs.t
│       └── prompt.ejs.t
└── init
    └── repo
        └── new-repo.ejs.t

コマンドを作る

それでは次に、先に紹介したコマンドhygen component new を作っていきましょう。
hygenは、hygen 任意の文字列 new といった形で自由にコマンドを設定できます。

コマンドを生成するためには、generatorコマンドを使用すると楽です。
以下のコマンドを実行して、hygen componentコマンドの下地を作ります。

pnpm hygen generator new component

実行後、_templateの中身は以下のように変わります。

_templates/
├── component
│   └── new
│       └── hello.ejs.t
├── generator
│   ├── help
│   │   └── index.ejs.t
│   ├── new
│   │   └── hello.ejs.t
│   └── with-prompt
│       ├── hello.ejs.t
│       └── prompt.ejs.t
└── init
    └── repo
        └── new-repo.ejs.t

先と比較すると、_template/component/new/hello.ejs.tが増えていることがわかります。
それでは、試しに作成したhygen componentコマンドを実行してみましょう。

pnpm hygen component new

実行すると、以下のファイルが作成されました。

app/hello.js
const hello = ```
Hello!
This is your first hygen template.

Learn what it can do here:

https://github.com/jondot/hygen
`` ` 

console.log(hello)

コードブロックが壊れるので、8行目に\s一個入れましたがそれ以外は生成物そのままのコードです。
hygen component newコマンドから、無事にファイルが生成されました。

これをみた上で、一度_template/component/newにあるhello.ejs.tを見てみたいと思います。

_templates/component/new/hello.ejs.t
---
to: app/hello.js
---
const hello = ```
Hello!
This is your first hygen template.

Learn what it can do here:

https://github.com/jondot/hygen
`` `

console.log(hello)

このファイル、何か見覚えがあるような気がしますね。

さらに、今度は_template/generator/newにあるhello.ejs.tを見てみましょう。
ちなみに、上記のファイルを生成するために使用したコマンドは、hygen generator newです。

_template/generator/new/hello.ejs.t
---
to: _templates/<%= name %>/<%= action || 'new' %>/hello.ejs.t
---
---
to: app/hello.js
---
const hello = ```
Hello!
This is your first hygen template.

Learn what it can do here:

https://github.com/jondot/hygen
`` `

console.log(hello)

はいもうわかりましたね。hygenはこういったコマンドです
わからなかったらコマンドを作るまで戻って再度読み直してください。わからなかった場合は、コードを一度一切読まないで説明文だけ読んでみるとわかりやすいと思います。

ユーザーに入力をさせる

ただ、これだけではちょっと便利だけど使い道に困るコマンド以上に価値はないです。
ここに、任意の文字列を入力させて生成場所や生成内容を操作していきたいと思います。

一度以下のコマンドを実行してhygen componentコマンドを削除して、新規にhygen componentコマンドを以下のコマンドで作り直しましょう。

rm -rf _template/component
pnpm hygen generator with-prompt component

なぜ new ではなく with-prompt を使用したのかというと、with-promptで生成されるprompt.jsが欲しかったからです。これがある以外には特にnewと差はありません。
ではこれがあるとどう異なるのか、試しにhygen componentを実行してみましょう。

pnpm hygen component with-prompt

すると、先とは違って今度はWhat's your message?と文字列の入力を求められたかと思います。

これで文字列入力が可能になりました。
なぜできるようになったかと言うと、hygenはコマンド実行時に対象のディレクトリ内にprompt.jsがあるとその内容に応じて設問を設けてくれるためです。
では、prompt.jsの中身を見てみましょう。

_template/component/with-prompt/prompt.js
// see types of prompts:
// https://github.com/enquirer/enquirer/tree/master/examples
//
module.exports = [
  {
    type: 'input',
    name: 'message',
    message: "What's your message?"
  }
]

フロント書いてる人ならなんとなく察したと思いますので、試しにmessageの中身を"What's your message?"からWhat's your name?に変えて実行してみたいと思います。

$ rm -rf app/
$ pnpm hygen component with-prompt
✔ What's your name? · ikea_shark

Loaded templates: _templates
       added: app/hello.js

設問が変わりましたね。
こうして質問内容はいくらでも変更ができます。

では、今度は入力させた文字列を使用して生成内容に変化を加えていきましょう。
hello.ejs.tの内容を以下のように書き換えてください。

---
to: app/hello.js
---
const hello = "I'm <%= message %>."

console.log(hello)

phpとかでテンプレートエンジン触ってた人には見覚えのある形式だと思います。

ついでに、with-promptと入力するの面倒なのでnewとかに変更しておきましょう。(横着したいだけなのでしなくてもいいです)

mv _templates/component/with-prompt _templates/component/new

それでは実行してみます。

$ rm -rf app/
$ pnpm hygen component new
✔ What's your name? · ikea_shark

Loaded templates: _templates
       added: app/hello.js
app/hello.js
const hello = "I'm ikea_shark."

console.log(hello)

このように、入力値ikea_sharkを生成するファイルに生かすことができました。
この<%= message %>messageですが、この値はprompt.jsの連想配列のうちnameのvalueが該当します。なので別の文字列を使用したい場合はこの値を任意のものに変えてあげてください。

なお、typeの値を他の値に変えることで、質問形式を変更できます。
そのあたりドキュメントに書かれて居ないので察する必要があるのですが、例えばselectにして連想配列にchoicesをstring[]のvalueを持つ形で追加してみると、こんな形になります。

$ pnpm hygen component new
? What's your name? … 
❯ foo
  bar
  baz
  ikea_shark

終わりに

今回は、prompt.jsの紹介までで終了しましたが、より柔軟な質問などを設けたい場合はindex.jsを追加することでできるようになります。最初に紹介した例で、入力値がatomなのに生成先のディレクトリ名が01-atomsなのは、この辺りを色々色々弄っている為です。
詳しくは、以下の公式ドキュメントを見てください。

失礼ながら、色々不足がちなドキュメントではあるので、より知見を深めたい場合はissueを覗いてみるといいかもしれません。
ただ、多くの方が解決したい課題はprompt.jsまでで解決できると思うので、興味が向かなければ無理に見に行かなくても良いとは思います。

個人的に、hygenで嬉しいところはチーム開発時にテストファイルの記載やstorybookの記載を強制できるところだと思っています。テストはまだしも、空気感によってはstorybookの作成って忘れられることがある項目だと思うんですよね。
特に初めて導入した際などは、この辺の矯正は重要で効果的じゃないかな、という認識です。

今回はフロントで楽になるツールとして紹介しましたが、このhygenが生きる環境は必ずしもフロントエンドに限った話ではないと思いますので、是非色々なシーンで試してみてください。

7
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?