nodejs-best-practices について
Node.js 開発者向けに、アーキテクチャ、フレームワーク、非同期処理、安全対策の選択を案内するガイドです。定型的な手順を押し付けず、プロジェクトの状況や要件に応じた判断を重視します。
主な機能
- 01状況に応じたフレームワーク選定
- 02ランタイムとモジュール方式の指針
- 03レイヤードアーキテクチャの原則
- 04非同期処理とイベントループの推奨事項
- 05入力検証とセキュリティチェックリスト
- 06テスト戦略とアンチパターン
活用シーン
- 01デプロイ先に適したフレームワークの選定
- 02成長するアプリケーションの設計
- 03非同期処理とイベントループのリスク確認
- 04検証・セキュリティ・テストの優先度評価
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ midudev/ autoskills --skill nodejs-best-practicesインストール後、Claude Code で/nodejs-best-practicesを入力して読み込まれたか確認します。
詳細
Node.js ベストプラクティス
2025 年における Node.js 開発の原則と意思決定。 コードパターンを暗記するのではなく、考えることを学びましょう。
使用する場面
Node.js のアーキテクチャを決定するとき、フレームワークを選定するとき、非同期パターンを設計するとき、あるいはセキュリティとデプロイのベストプラクティスを適用するときに、このスキルを使用してください。
⚠️ このスキルの使い方
このスキルは、コピーするための固定されたコードではなく、意思決定の原則を教えるものです。
- 不明な点がある場合は、ユーザーに好みを尋ねる
- コンテキストに基づいてフレームワークやパターンを選ぶ
- 毎回同じ解決策をデフォルトにしない
1. フレームワークの選定(2025 年)
決定木
What are you building?
│
├── Edge/Serverless (Cloudflare, Vercel)
│ └── Hono (zero-dependency, ultra-fast cold starts)
│
├── High Performance API
│ └── Fastify (2-3x faster than Express)
│
├── Enterprise/Team familiarity
│ └── NestJS (structured, DI, decorators)
│
├── Legacy/Stable/Maximum ecosystem
│ └── Express (mature, most middleware)
│
└── Full-stack with frontend
└── Next.js API Routes or tRPC
比較の原則
| 要因 | Hono | Fastify | Express |
|---|---|---|---|
| 最適な用途 | エッジ、サーバーレス | パフォーマンス | レガシー、学習 |
| コールドスタート | 最速 | 高速 | 中程度 |
| エコシステム | 成長中 | 良好 | 最大 |
| TypeScript | ネイティブ | 優秀 | 良好 |
| 学習曲線 | 低い | 中程度 | 低い |
尋ねるべき選定の質問:
- デプロイ先は何ですか?
- コールドスタート時間は重要ですか?
- チームに既存の経験はありますか?
- 維持すべきレガシーコードはありますか?
2. ランタイムの考慮事項(2025 年)
ネイティブ TypeScript
Node.js 22+: --experimental-strip-types
├── Run .ts files directly
├── No build step needed for simple projects
└── Consider for: scripts, simple APIs
モジュールシステムの決定
ESM (import/export)
├── Modern standard
├── Better tree-shaking
├── Async module loading
└── Use for: new projects
CommonJS (require)
├── Legacy compatibility
├── More npm packages support
└── Use for: existing codebases, some edge cases
ランタイムの選定
| ランタイム | 最適な用途 |
|---|---|
| Node.js | 汎用、最大のエコシステム |
| Bun | パフォーマンス、ビルトインのバンドラー |
| Deno | セキュリティ優先、ビルトインの TypeScript |
3. アーキテクチャの原則
レイヤード構造の概念
Request Flow:
│
├── Controller/Route Layer
│ ├── Handles HTTP specifics
│ ├── Input validation at boundary
│ └── Calls service layer
│
├── Service Layer
│ ├── Business logic
│ ├── Framework-agnostic
│ └── Calls repository layer
│
└── Repository Layer
├── Data access only
├── Database queries
└── ORM interactions
これが重要な理由:
- テスト容易性:レイヤーを独立してモックできる
- 柔軟性:ビジネスロジックに触れずにデータベースを差し替えられる
- 明確さ:各レイヤーが単一の責任を持つ
簡素化すべき場面:
- 小さなスクリプト → 単一ファイルで OK
- プロトタイプ → 構造が少なくても許容される
- 常に尋ねる:「これは成長するか?」
4. エラーハンドリングの原則
集中化されたエラーハンドリング
Pattern:
├── Create custom error classes
├── Throw from any layer
├── Catch at top level (middleware)
└── Format consistent response
エラー応答の考え方
Client gets:
├── Appropriate HTTP status
├── Error code for programmatic handling
├── User-friendly message
└── NO internal details (security!)
Logs get:
├── Full stack trace
├── Request context
├── User ID (if applicable)
└── Timestamp
ステータスコードの選択
| 状況 | ステータス | いつ |
|---|---|---|
| 不正な入力 | 400 | クライアントが無効なデータを送信した |
| 認証なし | 401 | 認証情報の欠落または無効 |
| 権限なし | 403 | 認証は有効だが、許可されていない |
| 見つからない | 404 | リソースが存在しない |
| 競合 | 409 | 重複または状態の競合 |
| バリデーション | 422 | スキーマは有効だがビジネスルールに失敗 |
| サーバーエラー | 500 | こちらの責任、すべてログに記録する |
5. 非同期パターンの原則
それぞれを使う場面
| パターン | 使う場面 |
|---|---|
async/await | 逐次的な非同期操作 |
Promise.all | 並列の独立した操作 |
Promise.allSettled | 一部が失敗する可能性がある並列処理 |
Promise.race | タイムアウトまたは最初の応答が勝つ場合 |
イベントループへの意識
I/O-bound (async helps):
├── Database queries
├── HTTP requests
├── File system
└── Network operations
CPU-bound (async doesn't help):
├── Crypto operations
├── Image processing
├── Complex calculations
└── → Use worker threads or offload
イベントループのブロッキングを避ける
- 本番環境では同期メソッドを決して使わない(fs.readFileSync など)
- CPU 負荷の高い処理をオフロードする
- 大きなデータにはストリーミングを使う
6. バリデーションの原則
境界でバリデーションする
Where to validate:
├── API entry point (request body/params)
├── Before database operations
├── External data (API responses, file uploads)
└── Environment variables (startup)
バリデーションライブラリの選定
| ライブラリ | 最適な用途 |
|---|---|
| Zod | TypeScript ファースト、型推論 |
| Valibot | より小さなバンドル(ツリーシェイク可能) |
| ArkType | パフォーマンス重視 |
| Yup | 既存の React Form での使用 |
バリデーションの考え方
- フェイルファスト:早期にバリデーションする
- 具体的に:明確なエラーメッセージ
- 信用しない:「内部」データであっても
7. セキュリティの原則
セキュリティチェックリスト(コードではない)
- 入力バリデーション:すべての入力をバリデーションする
- パラメータ化クエリ:SQL に文字列連結を使わない
- パスワードハッシュ:bcrypt または argon2
- JWT 検証:常に署名と有効期限を検証する
- レート制限:悪用から保護する
- セキュリティヘッダー:Helmet.js または同等のもの
- HTTPS:本番環境では常に
- CORS:適切に設定する
- シークレット:環境変数のみ
- 依存関係:定期的に監査する
セキュリティのマインドセット
Trust nothing:
├── Query params → validate
├── Request body → validate
├── Headers → verify
├── Cookies → validate
├── File uploads → scan
└── External APIs → validate response
8. テスト原則
テスト戦略の選択
| 種類 | 目的 | ツール |
|---|---|---|
| 単体 | ビジネスロジック | node:test、Vitest |
| 統合 | API エンドポイント | Supertest |
| E2E | 全フロー | Playwright |
テストすべきもの (優先順位)
- クリティカルパス: 認証、決済、中核ビジネス
- エッジケース: 空の入力、境界値
- エラーハンドリング: 失敗したときに何が起こるか?
- テストする価値がないもの: フレームワークのコード、自明な getter
組み込みテストランナー (Node.js 22+)
node --test src/**/*.test.ts
├── No external dependency
├── Good coverage reporting
└── Watch mode available
9. 避けるべきアンチパターン
❌ やってはいけないこと:
- 新しいエッジプロジェクトで Express を使う (Hono を使う)
- 本番コードで同期メソッドを使う
- コントローラーにビジネスロジックを置く
- 入力バリデーションを省略する
- シークレットをハードコードする
- バリデーションなしで外部データを信頼する
- CPU 処理でイベントループをブロックする
✅ やるべきこと:
- コンテキストに基づいてフレームワークを選ぶ
- 不明な場合はユーザーに好みを尋ねる
- 成長するプロジェクトにはレイヤードアーキテクチャを使う
- すべての入力をバリデーションする
- シークレットには環境変数を使う
- 最適化の前にプロファイリングする
10. 意思決定チェックリスト
実装する前に:
- ユーザーにスタックの好みを尋ねましたか?
- このコンテキストに合ったフレームワークを選びましたか? (単なるデフォルトではなく)
- デプロイ先を検討しましたか?
- エラーハンドリング戦略を計画しましたか?
- バリデーションのポイントを特定しましたか?
- セキュリティ要件を検討しましたか?
覚えておいてください: Node.js のベストプラクティスとは、パターンを暗記することではなく、意思決定に関するものです。すべてのプロジェクトは、その要件に基づいて新たに検討される価値があります。
制限事項
- このスキルは、タスクが上記のスコープに明確に一致する場合にのみ使用してください。
- 出力を、環境固有の検証、テスト、または専門家によるレビューの代わりとして扱わないでください。
- 必要な入力、権限、安全境界、または成功基準が欠けている場合は、停止して確認を求めてください。
コメント
Markdown 対応