Scaffoldを使用して、コンポーネントをワンコマンドで作成する
コンポーネント作成時のハードル
React 等でコンポーネントを作っていく際、一つのコンポーネントに対して複数のファイルを割り当てるという作り方はそれなりに多いと思います。例えば Next.js+Storybook 環境下で SASS を使用していたと想定して、以下のようなファイル構成を日頃作っているとします。
src/components/Sample01/index.ts
src/components/Sample01/Sample01.tsx
src/components/Sample01/Sample01.stories.tsx
src/components/Sample01/Sample01.module.scss
もしこれを手動で作るとなると、components フォルダに移動してコンポーネント用のフォルダを作り、さらにファイルを一から作るか、どこかからコピペ&名前変更という作業が待っています。結果、新しいコンポーネントを作る事に対して精神的なハードルが上がり、面倒だから機能ごとに切り分けずにまとめてしまおうという、悪魔のささやきが聞こえてくることになります。
これを解決するには共通部分をテンプレート化し、コマンド一発でさっと作れるようにすれば良いのです。
ツールを用意
この辺りの処理を簡単に出来るようにするためのツールを用意しました。
インストールは
yarn -D @node-libraries/scaffold
となります
コマンドラインから使う場合(グローバルインストールしていない前提)だと、npm run
か yarn
で起動してください
yarn scaffold
使い方
テンプレートの準備
テンプレート用のフォルダを作成し、その中に必要な設定を書き込みます。
テンプレート用のファイル名は、拡張子を.template
にする必要があります。わざわざそうしている理由は、開発環境のオートフォーマットで体裁が崩れるのを防ぐためです。
ファイル名なテキストの中身は以下の文字列が置換されます。この名前の部分はコマンド実行時に決定します。
{{{NAME}}}
-> ComponentName
{{{PATH}}}
-> ComponentPath
- templates/index.tsx.template
export * from "./{{{NAME}}}";
- templates/{{{NAME}}}.module.scss.template
.root {
}
- templates/{{{NAME}}}.tsx.template
import React, { FC } from 'react'
import styled from './{{{NAME}}}.module.scss'
interface Props {}
/**
* {{{NAME}}}
*
* @param {Props} { }
*/
export const {{{NAME}}}: FC<Props> = ({}) => {
return <div className={styled.root}>Sample</div>
}
- templates/{{{NAME}}}.tsx.template
import React from 'react'
import { {{{NAME}}} } from '.'
const StoryInfo = {
title: 'Components/{{{PATH}}}{{{NAME}}}',
component: {{{NAME}}}
}
export default StoryInfo
export const Primary = (args: Parameters<typeof {{{NAME}}}>[0]) => (
<>
<{{{NAME}}} {...args}></{{{NAME}}}>
</>
)
Primary.args = {} as Parameters<typeof {{{NAME}}}>[0]
Primary.parameters = {}
コマンド
-
./templates
からテンプレートを読み込み./src/components/Samples/Sample01
にコンポーネントを作成
scaffold create -t templates -o src/components Samples/Sample01
- 省略すると
-t
は./templates
、-o
は./src/components
がデフォルト
scaffold create Samples/Sample01
Scaffold の出力結果
- src/components/Samples/Sample01/index.tsx
export * from "./Sample01";
- src/components/Samples/Sample01/Sample01.module.scss
.root {
}
- src/components/Samples/Sample01/Sample01.stories.tsx
import React from "react";
import { Sample01 } from ".";
const StoryInfo = {
title: "Components/Samples/Sample01",
component: Sample01,
};
export default StoryInfo;
export const Primary = (args: Parameters<typeof Sample01>[0]) => (
<>
<Sample01 {...args}></Sample01>
</>
);
Primary.args = {} as Parameters<typeof Sample01>[0];
Primary.parameters = {};
- src/components/Samples/Sample01/Sample01.tsx
import React, { FC } from "react";
import styled from "./Sample01.module.scss";
interface Props {}
/**
* Sample01
*
* @param {Props} { }
*/
export const Sample01: FC<Props> = ({}) => {
return <div className={styled.root}>テスト</div>;
};
package.json でコマンドを簡略化
{
"scripts": { "sf": "scaffold create -t テンプレートフォルダ -o 出力フォルダ" }
}
というようにしておくと、
yarn sf コンポーネント名
という形で、オプションを簡略化できます。
まとめ
Scaffold があるだけで新しいコンポーネントを作る精神的なハードルは一気に下がり、開発速度の上昇にも繋がります。また、チーム内のコンポーネントの作り方のバラツキを押さえる効果もあります。導入すれば開発効率は確実に上がります。客の作業を自動化する前に、自分の作業を自動化することが重要です。
ちなみに今回作成したツールは nodejs の汎用プログラムなので、用途別にテンプレートさえ作成すれば様々なライブラリで使用できます。
Discussion