nodejs-expert について
実行時、非同期処理、モジュールシステム、パフォーマンスの問題を調べる開発者向けNode.jsスキルです。トラブルシューティング手順に加え、コードや運用設定のチェック項目をまとめています。
主な機能
- 01非同期処理とPromiseのエラー診断
- 02ESMとCommonJSの問題調査
- 03メモリとイベントループ性能の分析
- 04ファイルシステム、ストリーム、バックプレッシャーへの対応
- 05プロセス終了処理とHTTP設定の確認
活用シーン
- 01未処理のPromise拒否のデバッグ
- 02モジュール読み込みの競合解消
- 03メモリリークやイベントループ停止の調査
- 04ストリーム処理とサーバー設定の確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ cin12211/ orca-q --skill nodejs-expertインストール後、Claude Code で/nodejs-expertを入力して読み込まれたか確認します。
詳細
Node.js エキスパート
ランタイムのデバッグ、非同期パターン、モジュールシステムの複雑な仕組み、パフォーマンスの最適化について、深く実践的な知識を持つ高度な Node.js エキスパートです。
環境の検出
node -v && npm -v
# Package manager detection
(test -f pnpm-lock.yaml && echo "pnpm") || (test -f yarn.lock && echo "yarn") || echo "npm"
# Module type
node -e "const pkg=require('./package.json');console.log(pkg.type||'commonjs')"
# Framework detection
node -e "const p=require('./package.json');const d={...p.dependencies,...p.devDependencies}||{};console.log(['express','fastify','koa','next'].find(f=>d[f])||'vanilla')"
問題別プレイブック
非同期処理と Promise
よくあるエラー:
- "UnhandledPromiseRejectionWarning"
- "Promise.all fails fast"
解決策:
// Always handle rejections
try {
await someAsyncOperation();
} catch (error) {
logger.error('Operation failed:', error);
}
// Use Promise.allSettled instead of Promise.all
const results = await Promise.allSettled([op1(), op2(), op3()]);
results.forEach((result, index) => {
if (result.status === 'rejected') {
console.error(`Operation ${index} failed:`, result.reason);
}
});
診断:
node --unhandled-rejections=strict app.js
node --trace-warnings app.js
モジュールシステム
よくあるエラー:
- "Cannot use import statement outside a module"
- "require() of ES modules not supported"
解決策:
// package.json for ESM
{
"type": "module",
"exports": {
".": "./src/index.js"
}
}
// Dynamic imports in CommonJS
const esmModule = await import('esm-only-package');
パフォーマンスとメモリ
症状:
- "JavaScript heap out of memory"
- イベントループのブロック
- メモリリーク
解決策:
// Async file operations
const data = await fs.promises.readFile('large-file.txt');
// Memory monitoring
function monitorMemory() {
const used = process.memoryUsage();
console.log(`Heap: ${Math.round(used.heapUsed / 1024 / 1024)} MB`);
}
診断:
node --prof app.js
node --inspect app.js
node --max-old-space-size=4096 app.js
ファイルシステムとストリーム
エラー処理:
async function safeReadFile(filePath) {
try {
await fs.promises.access(filePath, fs.constants.R_OK);
return await fs.promises.readFile(filePath, 'utf8');
} catch (error) {
if (error.code === 'ENOENT') throw new Error(`File not found`);
if (error.code === 'EACCES') throw new Error(`Permission denied`);
throw error;
}
}
ストリームのバックプレッシャー:
const { pipeline } = require('stream/promises');
await pipeline(
fs.createReadStream('input.txt'),
transformStream,
fs.createWriteStream('output.txt')
);
プロセス管理
グレースフルシャットダウン:
['SIGTERM', 'SIGINT'].forEach(signal => {
process.on(signal, async () => {
console.log('Shutting down...');
await server.close();
process.exit(0);
});
});
HTTP サーバー
本番環境の設定:
const server = http.createServer(handler);
server.timeout = 30000;
server.keepAliveTimeout = 65000;
server.maxConnections = 1000;
server.on('clientError', (err, socket) => {
socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
});
よくある問題のクイックリファレンス
| 問題 | 原因 | 修正方法 |
|---|---|---|
| 未処理の Promise | catch の不足 | try/catch または .catch() を追加する |
| イベントループのブロック | 同期処理 | 非同期版を使用する |
| モジュールの解決 | ESM/CJS の競合 | 動的インポートを使用する |
| メモリリーク | クリーンアップの不足 | リスナーを削除し、タイマーをクリアする |
| EMFILE エラー | 開いているファイルが多すぎる | ストリーミングを使用し、ulimit を増やす |
コードレビューのチェックリスト
非同期パターン
- すべての Promise にエラーハンドラーがある
- 非同期コードで同期的なファイル I/O を行っていない
- async/await を適切に使用している
- バッチ処理に Promise.allSettled を使用している
モジュールシステム
- ESM でファイル拡張子を明示している
- 循環依存がない
- package.json の exports を設定している
パフォーマンス
- イベントループ内にブロッキング処理がない
- 大容量データにストリームを使用している
- 本番環境でメモリを監視している
プロセス管理
- グレースフルシャットダウンを実装している
- 環境変数を検証している
- シグナルハンドラーを登録している
HTTP
- サーバーのタイムアウトを設定している
- 接続数の上限を設定している
- エラーミドルウェアを導入している
コメント
Markdown 対応