React アプリケーションのボイラープレート CLI を作って使っている話

この記事は [ミクシィグループ Advent Calendar 2019](https://qiita.com/advent-calendar/2019/mixi) の5日目の記事です。

React で CLI というと [create-react-app](https://create-react-app.dev/) が有名です。
格好良いベースを作ってくれるのですが個人的には依存 package が多いので、自分用の CLI を作ってそちらを使っています。

## @yami-beta/create-ts-app

TypeScript を使ったアプリケーションのベースを作る対話型のインターフェースを持った CLI ツールです。
https://www.npmjs.com/package/@yami-beta/create-ts-app
![create-ts-app.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31403/f3d5a91e-f681-8866-abf1-8a807dc8cb82.gif)
意外と色々な package を用意する必要がある ESLint + Prettier の設定を含めていたり、author や LICENSE を設定できます。
（あくまで個人用なので自分の好みによせたボイラープレートになっています）

現在は React のシンプルなボイラープレートしかありませんが

- React, React Router, Redux 等が含まれた Single Page Application
- express によるサーバアプリケーション

のボイラープレートを追加していく予定です。

## 仕組み

この CLI ですが [SAO](https://saojs.org/) というライブラリを使って実装しています。
（[create-nuxt-app](https://github.com/nuxt/create-nuxt-app) も SAO を利用していたりします）

以下のようなコードを書くことで対話型のインターフェースを用意したり、テンプレートからファイルをコピーやリネームといったことが出来ます。

```javascript
module.exports = {
  prompts() {
    return [
      {
        name: 'name',
        message: 'What is the name of the new project',
        default: this.outFolder,
        filter: val => val.toLowerCase()
      }
    ]
  },
  actions: [
    {
      type: 'add',
      files: '**'
    },
    {
      type: "move",
      patterns: {
        "LICENSE_*": "LICENSE"
      }
    }
  ],
  async completed() {
    this.gitInit()
    await this.npmInstall()
    this.showProjectTips()
  }
}
```

`@yami-beta/create-ts-app` では [このような実装](https://github.com/yami-beta/create-ts-app/blob/eba210e8bb4d002ffcc6cf3fb0d995fc40ad4827/src/saofile.ts) になっています。
一部を抜粋すると、以下のようにコマンド実行時の回答に応じて package.json に記載する依存関係を編集することも可能です。

```typescript
const config = {
  actions() {
    const { answers } = this;
    return [
      // 略
      {
        type: "modify",
        files: "package.json",
        handler(data: any, filepath: string) {
          return {
            name: answers.name || data.name,
            version: answers.version || data.version,
            main: data.main,
            author: answers.author,
            license: answers.license || data.license,
            scripts: data.scripts,
            dependencies: {
              ...data.dependencies
            },
            devDependencies: {
              ...data.devDependencies,
              "@typescript-eslint/eslint-plugin": answers.features.includes(
                "eslint"
              )
                ? data.devDependencies["@typescript-eslint/eslint-plugin"]
                : undefined,
              "@typescript-eslint/parser": answers.features.includes("eslint")
                ? data.devDependencies["@typescript-eslint/parser"]
                : undefined,
              eslint: answers.features.includes("eslint")
                ? data.devDependencies["eslint"]
                : undefined,
              "eslint-config-prettier":
                answers.features.includes("eslint") &&
                answers.features.includes("prettier")
                  ? data.devDependencies["eslint-config-prettier"]
                  : undefined,
              "eslint-plugin-prettier":
                answers.features.includes("eslint") &&
                answers.features.includes("prettier")
                  ? data.devDependencies["eslint-plugin-prettier"]
                  : undefined,
              prettier: answers.features.includes("prettier")
                ? data.devDependencies["prettier"]
                : undefined
            }
          };
        }
      },
      // 略
    ].filter(Boolean);
  }
};
```

## CLI を作るほどでもない場合

ボイラープレートは欲しいけれども CLI を作るほどでは無い、という場合もあるかと思います。
そういう場合は GitHub のテンプレートリポジトリでボイラープレートを活用する方法があります。

- https://help.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-template-repository
- https://help.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-from-a-template

詳細は上記のドキュメントを参照してください。

## まとめ

- React アプリケーションのボイラープレートを生成する CLI を作っている
    - テンプレートからファイルをコピー、リネーム、編集することが出来るので複数のボイラープレート生成が可能
- 手軽にボイラープレートを作る場合は GitHub のテンプレートリポジトリが活用出来そう

### 備考

- [SAO](https://saojs.org/) という見覚えのある名前ですが [egoist](https://github.com/egoist) 氏のライブラリです