共有設定パッケージ
共有設定パッケージとは
モノレポでは、各パッケージで同じ ESLint や TypeScript の設定を使用することが一般的です。これらの設定を共有パッケージとして切り出すことで、以下のメリットが得られます。
- 設定の一元管理
- 変更時の反映が容易
- 新規パッケージ追加時の設定コストを削減
このテンプレートでは、以下の共有設定パッケージを提供しています。
| パッケージ | 説明 |
|---|---|
@monorepo/typescript-config |
TypeScript の基本設定 |
@monorepo/eslint-config |
ESLint Flat Config + Prettier 統合 |
@monorepo/typescript-config
package.json
{
"name": "@monorepo/typescript-config",
"private": true,
"exports": "./tsconfig.json",
"devDependencies": {
"rimraf": "catalog:",
"typescript": "catalog:"
}
}
exports フィールドで tsconfig.json をエクスポートすることで、他のパッケージから extends で参照できます。
tsconfig.json
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"target": "ES2021",
"module": "ESNext",
"lib": ["ES2021"],
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"esModuleInterop": true,
"isolatedModules": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"types": ["node"]
}
}
利用側での参照
{
"extends": "@monorepo/typescript-config"
}
@monorepo/eslint-config
package.json
{
"name": "@monorepo/eslint-config",
"type": "module",
"private": true,
"exports": "./index.js",
"devDependencies": {
"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "^9.37.0",
"@typescript-eslint/eslint-plugin": "^8.46.1",
"@typescript-eslint/parser": "^8.46.1",
"eslint": "catalog:",
"eslint-config-prettier": "^10.1.8",
"eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-boundaries": "^5.1.0",
"eslint-plugin-import": "2.32.0",
"eslint-plugin-only-warn": "^1.1.0",
"eslint-plugin-prettier": "^5.5.4",
"eslint-plugin-turbo": "^2.6.0",
"prettier": "catalog:",
"typescript-eslint": "^8.46.1"
}
}
ESLint Flat Config
ESLint 9.0 で導入された Flat Config 形式を使用しています。
import js from '@eslint/js';
import eslintConfigPrettier from 'eslint-config-prettier';
import boundariesPlugin from 'eslint-plugin-boundaries';
import importPlugin from 'eslint-plugin-import';
import turboPlugin from 'eslint-plugin-turbo';
import tseslint from 'typescript-eslint';
export const baseConfig = [
{
ignores: ['dist/**', 'build/**', 'node_modules/**', 'eslint.config.mjs'],
},
js.configs.recommended,
eslintConfigPrettier,
...tseslint.configs.recommended,
{
plugins: {
boundaries: boundariesPlugin,
import: importPlugin,
turbo: turboPlugin,
},
rules: {
'turbo/no-undeclared-env-vars': 'warn',
'import/order': [
'error',
{
groups: [['builtin', 'external', 'internal'], ['parent', 'sibling', 'index', 'object'], 'type'],
'newlines-between': 'always',
alphabetize: { order: 'asc', caseInsensitive: true },
},
],
},
},
];
利用側での参照
import { baseConfig } from '@monorepo/eslint-config';
export default [
...baseConfig,
{
// パッケージ固有の設定
},
];
TypeScript Project References の設計
このテンプレートでは、TypeScript の Project References を活用した設計を採用しています。
設計思想: VS Code と tsc の挙動一致
最も重要な設計目標は、VS Code のエディタ内 TypeScript と CLI の tsc コマンドで同じ挙動を実現することです。
従来の問題として、以下のような事象がよく発生していました。
- VS Code ではエラーにならないのに、
tscコマンドでエラーになる - 逆に、
tscでは通るのに VS Code でエラーが表示される - CI で落ちる原因がローカルで再現できない
Project References を適切に設定することで、これらの問題を防止できます。
ファイル構成
apps/server/
├── tsconfig.json # ベース設定 + references
├── tsconfig.build.json # 本番ビルド用
├── tsconfig.debug.json # 開発/デバッグ用
└── tsconfig.spec.json # テスト用
tsconfig.json(ベース設定)
{
"extends": "@monorepo/typescript-config",
"compilerOptions": {
"module": "nodenext",
"moduleResolution": "nodenext",
"outDir": "./dist",
"target": "ES2023",
"incremental": true,
"strictNullChecks": true
},
"references": [{ "path": "./tsconfig.build.json" }, { "path": "./tsconfig.spec.json" }]
}
ポイント:
referencesで他の設定ファイルを参照- VS Code はこのファイルを読み込み、
referencesを辿って型情報を取得
tsconfig.build.json(本番ビルド用)
{
"extends": "./tsconfig.json",
"include": ["src/**/*.ts"],
"exclude": [".turbo", "coverage", "dist", "node_modules", "src/**/*spec.ts"],
"compilerOptions": {
"outDir": "./dist",
"composite": true,
"rootDir": "src",
"removeComments": true,
"sourceMap": false,
"tsBuildInfoFile": "./.tsbuildinfo/build.tsbuildinfo",
"types": ["node"]
}
}
ポイント:
composite: trueで Project References を有効化tsBuildInfoFileで増分ビルド情報を分離- テストファイル(
*.spec.ts)を除外
tsconfig.debug.json(開発/デバッグ用)
{
"extends": "./tsconfig.json",
"include": ["src/**/*.ts"],
"exclude": ["node_modules", "test", "dist", "**/*spec.ts", "prisma"]
}
ポイント:
nest startコマンドで使用- デバッグに必要なファイルのみを含める
tsconfig.spec.json(テスト用)
{
"extends": "./tsconfig.json",
"include": ["src/**/*.ts", "src/**/*.spec.ts", "test/**/*.spec.ts", "test/**/*.e2e-spec.ts"],
"exclude": [".turbo", "coverage", "dist", "node_modules"],
"compilerOptions": {
"composite": true,
"tsBuildInfoFile": "./.tsbuildinfo/spec.tsbuildinfo",
"types": ["node", "jest"]
}
}
ポイント:
- テストファイルを含める
- Jest の型定義を追加
- ビルド情報をビルド用と分離
増分ビルドの最適化
tsBuildInfoFile を .tsbuildinfo/ ディレクトリに分離することで、以下のメリットが得られます。
- キャッシュの分離 - ビルド用とテスト用で別々のキャッシュ
- 高速な再ビルド - 変更されたファイルのみ再コンパイル
- クリーンな管理 -
.tsbuildinfo/ディレクトリごと削除可能
VS Code との連携
エディタ内型チェック
VS Code は tsconfig.json を読み込み、references を辿って型情報を取得します。これにより、エディタ内の型チェックと tsc コマンドの結果が一致します。
型チェックコマンド
{
"scripts": {
"tsc": "pnpm tsc:build && pnpm tsc:test",
"tsc:build": "tsc --noEmit --project tsconfig.build.json",
"tsc:test": "tsc --noEmit --project tsconfig.spec.json"
}
}
ビルド用とテスト用を分けて型チェックすることで、CI でも同じ挙動を実現します。
まとめ
共有設定パッケージと TypeScript Project References を組み合わせることで、以下のメリットが得られます。
- 設定の一元管理 - ESLint・TypeScript 設定を共有パッケージで管理
- VS Code と tsc の挙動一致 - エディタと CLI で同じ型チェック結果
- 増分ビルドの最適化 - Project References による高速な再ビルド
- CI との一貫性 - ローカルと CI で同じ挙動を保証
特に「エディタでは通るのに CI で落ちる」問題を防止できることは、開発体験に大きく貢献します。