[2025年] フロントエンド環境構築(React, TypeScript, Vite, Biome, lefthook)
概要
フロントエンドの環境構築を行ったのでそのメモ。自分の知識のアップデートも兼ねて。
ChatGPTには適宜相談しているが、最新の方法を確実に採用したいので、公式ドキュメントを参考にして、1つずつ手動で設定している。
コンセプト
シンプルなアプリケーションなので、Next.js のようなフレームワークは導入しない。状態管理も React 自体の機能で行う。
また、筆者はそれなりに CSS を書けるので、なるべく素の CSS を書ける環境にする。つまり TailwindCSS のようなクラスベースのスタイリングは選択しない。
環境構築
ここから環境構築を開始。
前提
まず、Github で空のレポジトリを作成。レポジトリ内には一切ファイルもディレクトリもない状態。ここからスタート。
Node.js(および npm)はインストール済み。
Vite
Vite を起点に環境を作っていく。
npm create vite@latest APP_NAME -- --template react-ts
無難に React と TypeScript を選択。APP_NAME には実際のアプリケーション名を入れる。
公式ドキュメントの通りに、依存パッケージのインストールと起動確認を行う。
npm install
npm run dev
無事に localhost で起動することを確認できた。
React Router v7
Next.js を利用しないので、ルーティングのために React Router を利用する。
npm i react-router
main.tsx に以下を追加。
import { BrowserRouter } from "react-router";
<BrowserRouter>
</BrowserRouter>
react-router-dom は不要になった?
React Hook Form & Valibot
フォーム機能を提供するので React Hook Form を入れる。
React v19 でフォームの機能が強化されたが、それでも依然として、複雑なフォームを提供するには React Hook Form の方が良さそう。
バリデーションライブラリには割りと新しめな Valibot を採用。
npm i react-hook-form valibot @hookform/resolvers
App.tsx を以下のように書き換え、最低限のフォームが動いていることを確認。
import { useForm } from 'react-hook-form'
import { object, string, type InferOutput } from 'valibot';
import { valibotResolver } from "@hookform/resolvers/valibot";
import './App.css'
const schema = object({
email: string(),
password: string(),
})
type FormSchema = InferOutput<typeof schema>
function App() {
const form = useForm<FormSchema>({
resolver: valibotResolver(schema),
})
const onSubmit = form.handleSubmit((data: FormSchema) => {
console.log(data)
})
return (
<form onSubmit={onSubmit}>
<input {...form.register('email')} />
<input {...form.register('password')} />
<button type="submit">Submit</button>
</form>
)
}
export default App
Lucide React
アイコンライブラリは入れておきたい。気に入ったものなら割りと何でも良いかなと思う。
npm install lucide-react
簡単に利用できて良い感じ。
import { Smile } from 'lucide-react';
<Smile size={100} />
Biome
リンターとフォーマッターには Biome を使う。ESLint と Prettier がテッパンだと思いつつ、少し冒険してみる。
npm install --save-dev --save-exact @biomejs/biome
npx @biomejs/biome init
biome.json が自動生成されるが、少し手直しして以下のように。
{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"vcs": {
"enabled": false,
"clientKind": "git",
"useIgnoreFile": false
},
"files": {
"ignoreUnknown": false,
"ignore": []
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 120,
"lineEnding": "lf",
"attributePosition": "auto"
},
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"javascript": {
"formatter": {
"jsxQuoteStyle": "double",
"quoteProperties": "asNeeded",
"trailingCommas": "all",
"semicolons": "asNeeded",
"arrowParentheses": "always",
"bracketSpacing": true,
"bracketSameLine": false,
"quoteStyle": "single",
"attributePosition": "auto"
}
}
}
以下のページを参考にした。
.vscode/settings.json がまだなかったので作成。
{
"editor.formatOnSave": true,
"[javascript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[javascriptreact]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[typescriptreact]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[css]": {
"editor.defaultFormatter": "biomejs.biome"
},
"editor.codeActionsOnSave": {
"source.fixAll.biome": "explicit",
"source.organizeImports.biome": "explicit"
}
}
settings.json が .gitignore されていたので、git 管理されるよう修正。
VSCode 拡張を入れる。
この時点で、ファイル保存するとフォーマッターが動くようになっているはず。
vite が入れたっぽい eslint 系は消してしまう。だいぶ依存性がシンプルになった。
npm uninstall eslint eslint-plugin-react-hooks eslint-plugin-react-refresh typescript-eslint @eslint/js
Git Hooks
Git Hooks の設定をしてしまう。
npm install lefthook --save-dev
lefthook.yml は以下の通り。git commit 時にフォーマットさせる。
pre-commit:
commands:
check:
glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,css}"
run: npx @biomejs/biome check --write --no-errors-on-unmatched --files-ignore-unknown=true --colors=off {staged_files}
stage_fixed: true
Husky/lint-staged より簡単で良い。
CSS Module
スタイリングは CSS Module で行う。vite なら特別な設定なしにそのまま使える。
Theme 管理やダークモード実装は、CSS 変数などを駆使して自前でつくる。
Vitest
テストには visest を使う。実行速度が速いので。
ちょっと複雑なロジックなどは、しっかりとユニットテストを書いておきたい。
npm install -D vitest
package.json にテストのコマンドを追加。
"test": "vitest",
コンポーネントテストの予定はなし。
まとめ
ここまでで、それなりにモダンな SPA 開発はできるようになったと思う。あとはサービスの特性に応じて、追加でパッケージを入れればOK。
最終的な package.json 内の依存は以下のようになっている。
"dependencies": {
"@hookform/resolvers": "^5.0.1",
"lucide-react": "^0.513.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-hook-form": "^7.57.0",
"react-router": "^7.6.2",
"valibot": "^1.1.0"
},
"devDependencies": {
"@biomejs/biome": "1.9.4",
"@types/react": "^19.1.2",
"@types/react-dom": "^19.1.2",
"@vitejs/plugin-react": "^4.4.1",
"globals": "^16.0.0",
"lefthook": "^1.11.13",
"typescript": "~5.8.3",
"vite": "^6.3.5",
"vitest": "^3.2.1"
}
Discussion