フロントエンド開発ガイドライン
目的
Suspenseベースのデータフェッチ、遅延ロード、適切なファイル構成、およびパフォーマンス最適化を重視した、モダンなReact開発のための包括的なガイドです。
このスキルを使用するタイミング
- 新しいコンポーネントやページの作成
- 新機能の構築
- TanStack Queryを使用したデータのフェッチ
- TanStack Routerによるルーティングの設定
- MUI v7を使用したコンポーネントのスタイリング
- パフォーマンスの最適化
- フロントエンドコードの整理
- TypeScriptのベストプラクティス
クイックスタート
新しいコンポーネントのチェックリスト
コンポーネントを作成しますか?以下のチェックリストに従ってください:
-
React.FC<Props>パターンをTypeScriptで使用 - 重いコンポーネントは遅延ロード:
React.lazy(() => import()) - ローディング状態のために
<SuspenseLoader>でラップ - データフェッチには
useSuspenseQueryを使用 - インポートエイリアス:
@/、~types、~components、~features - スタイル: 100行未満はインライン、100行超は別ファイル
- 子コンポーネントに渡すイベントハンドラには
useCallbackを使用 - デフォルトエクスポートはファイル下部
- ローディングスピナーによる早期リターンは禁止
- ユーザー通知には
useMuiSnackbarを使用
新しい機能のチェックリスト
機能を作成しますか?以下の構造をセットアップしてください:
-
features/{機能名}/ディレクトリを作成 - サブディレクトリを作成:
api/、components/、hooks/、helpers/、types/ - APIサービスファイルを作成:
api/{機能名}Api.ts -
types/にTypeScript型を設定 -
routes/{機能名}/index.tsxにルートを作成 - 機能コンポーネントを遅延ロード
- Suspense境界を使用
- 機能の
index.tsからパブリックAPIをエクスポート
インポートエイリアスクイックリファレンス
| エイリアス | 解決先 | 例 |
|---|---|---|
@/ | src/ | import { apiClient } from '@/lib/apiClient' |
~types | src/types | import type { User } from '~types/user' |
~components | src/components | import { SuspenseLoader } from '~components/SuspenseLoader' |
~features | src/features | import { authApi } from '~features/auth' |
定義場所: vite.config.ts 180-185行目
共通インポートチートシート
// React & 遅延ロード
import React, { useState, useCallback, useMemo } from 'react';
const Heavy = React.lazy(() => import('./Heavy'));
// MUIコンポーネント
import { Box, Paper, Typography, Button, Grid } from '@mui/material';
import type { SxProps, Theme } from '@mui/material';
// TanStack Query (Suspense)
import { useSuspenseQuery, useQueryClient } from '@tanstack/react-query';
// TanStack Router
import { createFileRoute } from '@tanstack/react-router';
// プロジェクトコンポーネント
import { SuspenseLoader } from '~components/SuspenseLoader';
// フック
import { useAuth } from '@/hooks/useAuth';
import { useMuiSnackbar } from '@/hooks/useMuiSnackbar';
// 型
import type { Post } from '~types/post';
トピックガイド
🎨 コンポーネントパターン
モダンなReactコンポーネントでは以下を使用:
- 型安全性のための
React.FC<Props> - コード分割のための
React.lazy() - ローディング状態のための
SuspenseLoader - 名前付きconst + デフォルトエクスポートパターン
重要な概念:
- 重いコンポーネント(DataGrid、チャート、エディタ)を遅延ロード
- 常に遅延ロードコンポーネントをSuspenseでラップ
- SuspenseLoaderコンポーネントを使用(フェードアニメーション付き)
- コンポーネント構造: Props → フック → ハンドラ → レンダリング → エクスポート
📖 完全ガイド: resources/component-patterns.md
📊 データフェッチ
主要パターン: useSuspenseQuery
- Suspense境界とともに使用
- キャッシュファースト戦略(API呼び出し前にグリッドキャッシュを確認)
isLoadingチェックを置き換え- ジェネリクスで型安全
APIサービス層:
features/{機能}/api/{機能}Api.tsを作成apiClientaxiosインスタンスを使用- 機能ごとにメソッドを一元化
- ルート形式:
/form/route(/api/form/routeではない)
📖 完全ガイド: resources/data-fetching.md
📁 ファイル構成
features/ vs components/:
features/: ドメイン固有(投稿、コメント、認証など)components/: 真に再利用可能(SuspenseLoader、CustomAppBarなど)
機能サブディレクトリ:
features/
my-feature/
api/ # APIサービス層
components/ # 機能コンポーネント
hooks/ # カスタムフック
helpers/ # ユーティリティ関数
types/ # TypeScript型
📖 完全ガイド: resources/file-organization.md
🎨 スタイリング
インライン vs 別ファイル:
- 100行未満: インライン
const styles: Record<string, SxProps<Theme>> - 100行超: 別ファイル
.styles.ts
主要な方法:
- MUIコンポーネントには
sxプロパティを使用 SxProps<Theme>で型安全- テーマへのアクセス:
(theme) => theme.palette.primary.main
MUI v7 Grid:
<Grid size={{ xs: 12, md: 6 }}> // ✅ v7構文
<Grid xs={12} md={6}> // ❌ 古い構文
📖 完全ガイド: resources/styling-guide.md
🛣️ ルーティング
TanStack Router - フォルダベース:
- ディレクトリ:
routes/my-route/index.tsx - コンポーネントを遅延ロード
createFileRouteを使用- ローダーにパンくずデータを含める
例:
import { createFileRoute } from '@tanstack/react-router';
import { lazy } from 'react';
const MyPage = lazy(() => import('@/features/my-feature/components/MyPage'));
export const Route = createFileRoute('/my-route/')({
component: MyPage,
loader: () => ({ crumb: 'My Route' }),
});
📖 完全ガイド: resources/routing-guide.md
⏳ ローディングとエラー状態
重要ルール: 早期リターン禁止
// ❌ 絶対にしない - レイアウトシフトの原因
if (isLoading) {
return <LoadingSpinner />;
}
// ✅ 常にこちら - 一貫したレイアウト
<SuspenseLoader>
<Content />
</SuspenseLoader>
理由: Cumulative Layout Shift (CLS)を防ぎ、より良いUXを提供
エラーハンドリング:
- ユーザーフィードバックには
useMuiSnackbarを使用 react-toastifyは絶対に使用しない- TanStack Queryの
onErrorコールバック
📖 完全ガイド: resources/loading-and-error-states.md
⚡ パフォーマンス
最適化パターン:
useMemo: 高コストな計算(フィルタ、ソート、マップ)useCallback: 子コンポーネントに渡すイベントハンドラReact.memo: 高コストなコンポーネント- デバウンスされた検索(300-500ms)
- メモリーリーク防止(useEffect内のクリーンアップ)
📖 完全ガイド: resources/performance.md
📘 TypeScript
標準:
- 厳格モード、
any型禁止 - 関数に明示的な戻り値の型
- 型インポート:
import type { User } from '~types/user' - JSDoc付きのコンポーネントプロパティインターフェース
📖 完全ガイド: resources/typescript-standards.md
🔧 共通パターン
カバーするトピック:
- Zodバリデーションを使用したReact Hook Form
- DataGridラッパー契約
- ダイアログコンポーネント標準
- 現在のユーザーを取得する
useAuthフック - キャッシュ無効化を含むミューテーションパターン
📖 完全ガイド: resources/common-patterns.md
📚 完全な例
完全な動作例:
- すべてのパターンを使用したモダンなコンポーネント
- 完全な機能構造
- APIサービス層
- 遅延ロード付きルート
- Suspense + useSuspenseQuery
- バリデーション付きフォーム
📖 完全ガイド: resources/complete-examples.md
ナビゲーションガイド
| 必要な操作... | このリソースを読む |
|---|---|
| コンポーネントを作成する | component-patterns.md |
| データをフェッチする | data-fetching.md |
| ファイル/フォルダを整理する | file-organization.md |
| コンポーネントをスタイリングする | styling-guide.md |
| ルーティングを設定する | routing-guide.md |
| ローディング/エラーを処理する | loading-and-error-states.md |
| パフォーマンスを最適化する | performance.md |
| TypeScript型 | typescript-standards.md |
| フォーム/認証/DataGrid | common-patterns.md |
| 完全な例を見る | complete-examples.md |
基本原則
- 重いものはすべて遅延ロード: ルート、DataGrid、チャート、エディタ
- ローディングにはSuspense: SuspenseLoaderを使用し、早期リターンは避ける
- useSuspenseQuery: 新しいコードの主要なデータフェッチパターン
- 機能は整理する: api/、components/、hooks/、helpers/のサブディレクトリ
- サイズに基づいたスタイル: 100行未満はインライン、100行超は別ファイル
- インポートエイリアス: @/、~types、~components、~featuresを使用
- 早期リターン禁止: レイアウトシフトを防止
- useMuiSnackbar: すべてのユーザー通知に使用
クイックリファレンス: ファイル構造
src/
features/
my-feature/
api/
myFeatureApi.ts # APIサービス
components/
MyFeature.tsx # メインコンポーネント
SubComponent.tsx # 関連コンポーネント
hooks/
useMyFeature.ts # カスタムフック
useSuspenseMyFeature.ts # Suspenseフック
helpers/
myFeatureHelpers.ts # ユーティリティ
types/
index.ts # TypeScript型
index.ts # パブリックエクスポート
components/
SuspenseLoader/
SuspenseLoader.tsx # 再利用可能なローダー
CustomAppBar/
CustomAppBar.tsx # 再利用可能なアプリバー
routes/
my-route/
index.tsx # ルートコンポーネント
create/
index.tsx # ネストされたルート
モダンなコンポーネントテンプレート(クイックコピー用)
import React, { useState, useCallback } from 'react';
import { Box, Paper } from '@mui/material';
import { useSuspenseQuery } from '@tanstack/react-query';
import { featureApi } from '../api/featureApi';
import type { FeatureData } from '~types/feature';
interface MyComponentProps {
id: number;
onAction?: () => void;
}
export const MyComponent: React.FC<MyComponentProps> = ({ id, onAction }) => {
const [state, setState] = useState<string>('');
const { data } = useSuspenseQuery({
queryKey: ['feature', id],
queryFn: () => featureApi.getFeature(id),
});
const handleAction = useCallback(() => {
setState('updated');
onAction?.();
}, [onAction]);
return (
<Box sx={{ p: 2 }}>
<Paper sx={{ p: 3 }}>
{/* コンテンツ */}
</Paper>
</Box>
);
};
export default MyComponent;
完全な例については、resources/complete-examples.mdを参照してください。
関連スキル
- error-tracking: Sentryを使用したエラートラッキング(フロントエンドにも適用)
- backend-dev-guidelines: フロントエンドが利用するバックエンドAPIパターン
スキルステータス: 最適なコンテキスト管理のためのプログレッシブローディングを使用したモジュール構造