GASHIRA-BLOG

JSでscaffoldな環境作り入門【React + scaffdog】

公開日: 2023年3月7日

最終更新日: 2023年5月10日

Nest.jsを使用していると、generateコマンドを使用してcontrollerやmoduleなどのテンプレートを生成することができます。

フロントエンド開発をしていても、.tsxファイルや.specファイルをお決まりのように作成することになるでしょう。

scaffoldという言葉自体の正しい意味合いはわかってないのですが、「足場」という意味があるようで、要は開発を行う時にコマンドでテンプレート(足場)を用意できる環境を構築できれば scaffold な環境と今回は定義しようと思います。

JavaScriptでのscaffoledライブラリ

scaffoldな環境を用意するにあたって、scaffdogというライブラリを使用したいと思います。

scaffdogはconfigファイルとmarkdownファイルを用意して生成するライブラリとなります。

対象者

コードの書き方を統一できるように取り組みたい方

ゴール

Reactの環境でコンポーネントを作成するためのテンプレートが自動生成される状態になる。

scaffdog@2.5.0

準備

インストールや進め方は基本的にはGetting startedを読むと進められると思います。

まずはディレクトリを作成し、scaffdogをインストールしましょう。

npx create-react-app scaff-js --template typescript
cd scaff-js
npm install --save-dev scaffdog

次に、configとmarkdownを作成しましょう。

scaffdogにはありがたいことにinitコマンドが用意されています。

npx scaffdog init
? Please enter a document name. components

componentsという名前でmarkdownを自動生成しました。

そして、自動生成を実行するために毎回npxコマンドを実行するのも大変なので、package.jsonのscriptに生成コマンドを登録しましょう。

{
	"scripts": {
    // ...
+   "g": "scaffdog generate"
  }
}

ここまで準備ができたら実行するまでの準備は完了です。

次に生成するファイルの設定をしていきましょう!

markdownファイルの修正

では、先ほど生成された .scaffdog/components.md をエディタにて開きましょう。

ではこの components.md を編集してコンポーネントの tsx ファイルとテストを自動生成する準備をしましょう。

---
name: 'components'
root: './components/'
output: '**/*'
ignore: []
questions:
  value: 'コンポーネントの名前を指定してください'
---

# `{{ inputs.value | pascal }}/index.tsx`

```typescript
const {{ inputs.value | pascal }}: React.FC = () => {
  return (
    <div>
    </div>
  )
}

export {{ inputs.value | pascal }};
```

# `{{ inputs.value | pascal }}/{{ inputs.value | pascal }}.spec.ts`

```typescript
{{- fileName := inputs.value | pascal -}}
import { render, screen } from '@testing-library/react';
import {{ fileName }} from './{{ fileName }}';

describe('{{  fileName }}', () => {
    it('スナップショットテスト', () => {
      render(<{{ fileName }} />);
      expect(linkElement).toMatchSnapshot();
    })
});
```

これで、自動作成する準備ができました!

自動生成の実行

ではmarkdownファイルも作成できたので生成コマンドを実行しましょう。

今回はボタンコンポーネントを作成しましょう。

npm run g

このコマンドを実行することで作成のためのやりとりが始まります。

? Please select a document. (Use arrow keys)
❯ components 

このように選択肢が出ると思うのでcomponentsが選択された状態で Enter を押しましょう。

 Output destination directory: "./src/components/"                                                                                                                                                           
? コンポーネントの名前を指定してください 

と表示されるので button と入力しましょう。

🐶 Generated 2 files!                                                                                                                                                                                         
                                                                                                                                                                                                              
     ✔ src/components/Button/index.tsx                                                                                                                                                                        
     ✔ src/components/Button/Button.spec.tsx                                                                                                                                                                  
                                              

これで、ボタンコンポーネントが完成しました!

src/components/Button/index.tsx を開いてみましょう。

export const Button: React.FC = () => {
  return (
    <div>
    </div>
  )
}

マークダウンに記載したコードが出力されています!

これで、環境構築は完了したのであとは公式サイトを参考に構築していきましょう!

いくつかのポイントについて解説

scaffdogを使用するにあたって、いくつかのポイントを押さえるとドキュメントを読みやすくなりますので、説明を追加します。

変数代入処理のコツ

変数を代入するときに、改行を出力をしたくないブロックが発生すると思います。

その際には(サンプルでも使ってますが)ハイフン付きで囲うとトリミングが行われるので、改行なしで出力することができます。

{{- text := "hello" -}}
{{ text }} world
---
hello world

変数はテンプレートブロックのみのスコープ

かなり複雑な処理を書こうと思い、変数を上の方に定義して、再度下のブロックで使おうとしたところエラーとなりました。

しかし、この仕様はしっかりドキュメントを読めば書いてあるんですけどね。

# first.ts

```typescript
{{ text := "hello" }}
const hoge = {{ text }};
```

# second.ts

```typescript
const fuga = {{ text }}; ← ここでエラーが発生! text という変数が存在しない。
```

このエラーは頭を悩ませました。

Optionの書き方

上記サンプルを使用し続けると、__snapshot__などが選択肢に上がってきたりして、かなり面倒になると思います。

なので、Optionでignoreを追加することができます。

実際のプロジェクトでもこの設定を活用しておりまして

ignore: ['**/__snapshots__']

ignoreの箇所をこのように修正することで、snapshotのディレクトリが非表示となるので、選択しやすくなります。

最後に

いかがだったでしょう?

コードのベースを作るにあたって、毎回同じ処理を書いたりする手間が省けたり、コピペ警察の出番も減るのではないでしょうか。

scaffdogをもっと活用して、コードの品質を一定に保てるように精進して参りたいと思います。

何か感想や間違ってる点、質問などありましたらTwitterにてご連絡ください。