フロントエンド構築手順書¶
概要¶
本ドキュメントは、会計システムのフロントエンド環境を構築するための手順書です。
技術スタック¶
| カテゴリ | 技術 | バージョン |
|---|---|---|
| 言語 | TypeScript | ~5.5.0 |
| フレームワーク | React | ^18.3.0 |
| ビルドツール | Vite | ^5.4.0 |
| 状態管理 | TanStack Query | ^5.0.0 |
| ルーティング | React Router | ^6.26.0 |
| HTTP クライアント | Axios | ^1.7.0 |
| 日付処理 | Day.js | ^1.11.0 |
| 数値処理 | Decimal.js | ^10.4.0 |
| バリデーション | Zod | ^4.2.1 |
| 静的解析 | ESLint | ^9.0.0 |
| 静的解析 | eslint-plugin-sonarjs | ^3.0.5 |
| 循環参照検知 | dependency-cruiser | ^17.3.4 |
| フォーマッタ | Prettier | ^3.0.0 |
| 単体テスト | Vitest | ^2.0.0 |
| テストライブラリ | Testing Library | ^16.0.0 |
| API モック | MSW | ^2.0.0 |
| E2E テスト | Cypress | ^14.0.0 |
| カバレッジ | @vitest/coverage-v8 | ^2.0.0 |
| タスクランナー | Gulp | ^5.0.1 |
| API 生成 | Orval | ^7.0.0 |
| コード品質 | SonarQube Scanner | ^4.3.2 |
前提条件¶
以下のツールがインストールされていること:
- Node.js 20 以上
- npm 10 以上
- Git
ディレクトリ構成¶
apps/frontend/
├── package.json # パッケージ設定
├── tsconfig.json # TypeScript 設定
├── tsconfig.node.json # Node.js 用 TypeScript 設定
├── vite.config.ts # Vite 設定
├── eslint.config.js # ESLint 設定
├── .prettierrc # Prettier 設定
├── .prettierignore # Prettier 除外設定
├── .dependency-cruiser.cjs # 循環参照検知設定
├── gulpfile.js # Gulp タスク定義
├── .env.development # 開発環境変数
├── .env.production # 本番環境変数
├── index.html # HTML エントリポイント
├── public/ # 静的ファイル
├── cypress/ # E2E テスト
│ ├── e2e/
│ └── support/
└── src/
├── main.tsx # アプリケーションエントリポイント
├── App.tsx # ルートコンポーネント
├── App.test.tsx # App テスト
├── config.ts # 設定
├── queryClient.ts # TanStack Query 設定
├── vite-env.d.ts # Vite 型定義
├── api/ # API クライアント(Orval 生成)
│ ├── generated/
│ └── model/
├── components/ # 共通コンポーネント
├── features/ # 機能別モジュール
├── hooks/ # カスタムフック
│ └── useAuth.ts
├── mocks/ # MSW モック
│ ├── browser.ts
│ ├── handlers.ts
│ └── server.ts
├── pages/ # ページコンポーネント
├── providers/ # Context プロバイダー
│ └── AuthProvider.tsx
├── styles/ # スタイル
│ └── global.css
├── test/ # テスト設定
│ └── setup.ts
├── types/ # 型定義
└── utils/ # ユーティリティ
セットアップ手順¶
1. 依存関係のインストール¶
cd apps/frontend
npm install
2. 初期チェックの実行¶
npm run checkAndFix
3. 開発サーバーの起動¶
npm run dev
ブラウザで http://localhost:3000 にアクセス
4. 動作確認¶
# ビルド
npm run build
# テスト
npm run test:run
# Lint
npm run lint
# 循環参照チェック
npm run depcruise
npm スクリプト一覧¶
基本コマンド¶
| コマンド | 説明 |
|---|---|
npm run dev |
開発サーバー起動 |
npm run build |
本番ビルド |
npm run preview |
ビルド結果プレビュー |
テスト¶
| コマンド | 説明 |
|---|---|
npm run test |
テスト実行(ウォッチモード) |
npm run test:run |
テスト実行(1回) |
npm run test:ui |
テスト UI 起動 |
npm run test:coverage |
カバレッジ付きテスト |
品質チェック¶
| コマンド | 説明 |
|---|---|
npm run lint |
ESLint 実行 |
npm run lint:fix |
ESLint 自動修正 |
npm run format |
Prettier フォーマット |
npm run format:check |
Prettier チェック |
npm run depcruise |
循環参照チェック |
E2E テスト¶
| コマンド | 説明 |
|---|---|
npm run cypress |
Cypress GUI 起動 |
npm run cypress:run |
Cypress ヘッドレス実行 |
API 生成¶
| コマンド | 説明 |
|---|---|
npm run api:generate |
OpenAPI から API クライアント生成 |
npm run api:fetch |
OpenAPI 取得 + 生成 |
タスクランナー(Gulp)¶
| コマンド | 説明 |
|---|---|
npm run gulp |
Gulp タスク実行 |
npm run watch |
ファイル監視(テストのみ) |
npm run guard |
ファイル監視(lint + format + test) |
npm run check |
全体チェック(修正なし) |
npm run checkAndFix |
全体チェック(自動修正付き) |
npm run setup |
初期セットアップ |
Gulp タスク一覧¶
npx gulp --tasks
| タスク | 説明 |
|---|---|
test |
テスト実行 |
coverage |
カバレッジ付きテスト |
lint |
ESLint 実行 |
lintFix |
ESLint 自動修正 |
format |
Prettier フォーマット |
formatCheck |
Prettier チェック |
depcruise |
循環参照チェック |
build |
ビルド |
dev |
開発サーバー |
check |
全体チェック(修正なし) |
checkAndFix |
全体チェック(自動修正付き) |
guard |
ファイル監視(自動 lint + format + test) |
watchTask |
ファイル監視(テストのみ) |
default |
checkAndFix + guard |
設定ファイル¶
vite.config.ts¶
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},
server: {
port: 3000,
open: true,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
secure: false,
},
},
},
build: {
outDir: 'dist',
sourcemap: true,
},
test: {
globals: true,
environment: 'jsdom',
setupFiles: ['./src/test/setup.ts'],
include: ['src/**/*.{test,spec}.{ts,tsx}'],
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html'],
exclude: [
'node_modules/',
'src/api/generated/',
'src/api/model/',
'src/test/',
],
},
},
});
tsconfig.json の主要設定¶
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "bundler",
"strict": true,
"jsx": "react-jsx",
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}
静的解析設定¶
ESLint (9.x + sonarjs)¶
主要ルール:
- 循環的複雑度: 最大 7
- 認知的複雑度: 最大 15(sonarjs/cognitive-complexity)
- no-console: warn(warn, error は許可)
- no-debugger: error
- no-var: error
- prefer-const: error
設定ファイル: eslint.config.js
import sonarjs from 'eslint-plugin-sonarjs';
export default tseslint.config(
// ...
{
plugins: {
sonarjs,
},
rules: {
// 循環的複雑度の制限 - 7を超える場合はエラー
complexity: ['error', { max: 7 }],
// 認知的複雑度の制限 - 15を超える場合はエラー
'sonarjs/cognitive-complexity': ['error', 15],
// ...
},
}
);
dependency-cruiser¶
循環参照と未使用ファイルを検知します。
設定ファイル: .dependency-cruiser.cjs
主要ルール:
- no-circular: 循環参照を禁止(error)
- no-orphans: 未使用ファイルを警告(warn)
- not-to-deprecated: 非推奨モジュールへの依存を警告(warn)
- no-non-package-json: package.json 未記載パッケージへの依存を禁止(error)
実行:
npm run depcruise
依存関係の可視化(Graphviz が必要):
npx depcruise src --include-only "^src" --output-type dot | dot -T svg > dependency-graph.svg
Prettier¶
設定ファイル: .prettierrc
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 100
}
テスト¶
テスト構成¶
| 種類 | 対象 | ツール |
|---|---|---|
| 単体テスト | コンポーネント、フック | Vitest, Testing Library |
| 統合テスト | API 連携 | Vitest, MSW |
| E2E テスト | ユーザーフロー | Cypress |
Vitest 設定¶
// vite.config.ts
test: {
globals: true,
environment: 'jsdom',
setupFiles: ['./src/test/setup.ts'],
include: ['src/**/*.{test,spec}.{ts,tsx}'],
}
MSW(Mock Service Worker)¶
API モックの設定:
// src/mocks/handlers.ts
import { http, HttpResponse } from 'msw';
export const handlers = [
http.post('/api/auth/login', async ({ request }) => {
const { username, password } = await request.json();
if (username === 'admin' && password === 'password') {
return HttpResponse.json({
accessToken: 'mock-access-token',
user: { id: 1, username: 'admin', role: 'ADMIN' },
});
}
return new HttpResponse(null, { status: 401 });
}),
];
Cypress E2E テスト¶
// cypress/e2e/sample.cy.ts
describe('App', () => {
it('トップページにアクセスできる', () => {
cy.visit('/');
cy.contains('財務会計システム');
});
});
開発ワークフロー¶
Guard モード(推奨)¶
ファイル変更時に自動で lint、format、test を実行:
npm run guard
TDD サイクル¶
- テストを書く(Red)
- テストをパスする最小限のコードを書く(Green)
- リファクタリング(Refactor)
# テストウォッチモードで開発
npm run test
コミット前チェック¶
npm run checkAndFix
API クライアント生成¶
バックエンドの OpenAPI 仕様から TypeScript クライアントを自動生成:
# バックエンドが起動している状態で
npm run api:fetch
生成先:
- src/api/generated/ - API クライアント
- src/api/model/ - 型定義
環境変数¶
.env.development¶
# OpenAPI spec のパスに /api が含まれているため、baseURL には /api を含めない
VITE_API_BASE_URL=http://localhost:8080
VITE_ENABLE_MSW=true
.env.production¶
# OpenAPI spec のパスに /api が含まれているため空
VITE_API_BASE_URL=
VITE_ENABLE_MSW=false
アプリケーション内での使用:
// src/config.ts
export const config = {
// OpenAPI spec のパスに /api が含まれているため、baseURL は空
apiBaseUrl: import.meta.env.VITE_API_BASE_URL || '',
enableMsw: import.meta.env.VITE_ENABLE_MSW === 'true',
};
トラブルシューティング¶
Node.js バージョンエラー¶
解決方法: Node.js 20 以上がインストールされていることを確認:
node -v
# v20.0.0 以上であること
ESLint エラー¶
sonarjs プラグインエラー:
npm install -D eslint-plugin-sonarjs
循環参照エラー¶
dependency-cruiser で循環参照が検出された場合:
npm run depcruise
# error no-circular: src/module-a.ts → src/module-b.ts → src/module-a.ts
解決方法: 1. 依存性逆転の原則を適用 2. 共通モジュールを抽出 3. レイヤーアーキテクチャを導入
Gulp エラー¶
# タスク一覧確認
npx gulp --tasks
# 個別タスク実行
npx gulp test
ビルドエラー¶
# キャッシュクリア
rm -rf node_modules/.vite
npm run build
テストエラー¶
# テスト環境リセット
rm -rf node_modules
npm install
npm run test:run
SonarQube 連携¶
概要¶
SonarQube を使用してコード品質を継続的に監視します。
設定ファイル¶
sonar-project.properties:
sonar.projectKey=accounting-frontend
sonar.projectName=Accounting Frontend
sonar.sources=src
sonar.tests=src
sonar.test.inclusions=**/*.test.ts,**/*.test.tsx
sonar.exclusions=**/node_modules/**,**/dist/**,**/coverage/**
sonar.typescript.lcov.reportPaths=coverage/lcov.info
sonar.eslint.reportPaths=eslint-report.json
環境変数の設定¶
.env.local.example をコピーして .env.local を作成し、SonarQube の設定を行います。
cp .env.local.example .env.local
.env.local:
SONAR_HOST_URL=http://localhost:9000
SONAR_TOKEN=your-token-here
解析の実行¶
# SonarQube サーバーが起動していること
# 解析実行(カバレッジ + ESLint レポート生成 + SonarQube 送信)
npm run sonar
npm スクリプト¶
| コマンド | 説明 |
|---|---|
npm run sonar |
カバレッジ + ESLint レポート生成 + SonarQube 解析 |
npm run sonar:ci |
CI 用(レポート生成済みの場合) |
npm run lint:report |
ESLint レポートを JSON 形式で出力 |
結果の確認¶
http://localhost:9000/dashboard?id=accounting-frontend
CI/CD¶
GitHub Actions¶
.github/workflows/frontend-ci.yml でフロントエンドの CI を実行します。
トリガー:
- main / develop ブランチへの push
- main / develop ブランチへの pull request
- apps/frontend/** のファイル変更時
実行内容: 1. 依存関係のインストール 2. ESLint 実行 3. フォーマットチェック 4. 循環参照チェック 5. テスト + カバレッジ 6. ビルド
アーティファクト:
- coverage-report: カバレッジレポート
- build-artifacts: ビルド成果物
ワークフロー例¶
name: Frontend CI
on:
push:
branches: [ main, develop ]
paths:
- 'apps/frontend/**'
jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
working-directory: apps/frontend
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: apps/frontend/package-lock.json
- run: npm ci
- run: npm run lint
- run: npm run test:coverage
- run: npm run build