TypeScript 共有可能な tsconfig 設計:`tsconfig/bases`で複数パッケージを一括最適化

複数の TypeScript パッケージを管理する際、各パッケージで似たような tsconfig.json
を何度も書いた経験はありませんか?
モノレポやマルチパッケージ構成では、設定ファイルの重複やメンテナンス負荷が大きな課題となります。そこで注目されているのが @tsconfig/bases
パッケージを活用した共有可能な設定設計です。
本記事では、TypeScript 設定の共有化から継承ベースの最適化まで、段階的に解説していきます。
背景
TypeScript プロジェクトが大規模化するにつれて、設定管理の複雑さが顕著になってきました。
複数パッケージでの設定重複問題
現代のフロントエンド開発では、一つのプロジェクトで複数のパッケージを管理することが一般的になっています。例えば、以下のような構成をよく見かけます。
typescript// packages/api/tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"outDir": "./dist",
"rootDir": "./src"
}
}
typescript// packages/web/tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"module": "esnext",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"jsx": "react-jsx",
"moduleResolution": "node"
}
}
上記のように、基本的な設定項目が各パッケージで重複してしまいます。これでは以下の問題が発生します。
プロジェクト全体の設定管理における主な課題を図で示します。
mermaidflowchart TD
project[プロジェクトルート] --> api[API パッケージ]
project --> web[Web パッケージ]
project --> shared[共有ライブラリ]
api --> api_config[独自 tsconfig.json]
web --> web_config[独自 tsconfig.json]
shared --> shared_config[独自 tsconfig.json]
api_config --> duplicate1[重複設定]
web_config --> duplicate2[重複設定]
shared_config --> duplicate3[重複設定]
duplicate1 --> maintenance_issue[メンテナンス負荷]
duplicate2 --> maintenance_issue
duplicate3 --> maintenance_issue
図で理解できる要点:
- 各パッケージが独自の設定ファイルを持つ構造
- 基本設定の重複による管理コスト増加
- 設定変更時の影響範囲拡大
tsconfig.json メンテナンス課題
個別の tsconfig.json
ファイルを管理することで生じる具体的な課題は以下の通りです。
設定の同期作業が手動になる TypeScript のバージョンアップ時や新機能の活用時に、全パッケージの設定を手動で更新する必要があります。これは時間がかかるだけでなく、更新漏れのリスクも伴います。
設定項目の意味理解が必要
各開発者が compilerOptions
の詳細を理解していないと、適切な設定変更ができません。特に moduleResolution
や target
などの相互依存関係のある設定では、誤った組み合わせによるビルドエラーが発生することがあります。
プロジェクト固有設定との境界が曖昧 どの設定が全プロジェクト共通で、どれがパッケージ固有なのかが不明確になりがちです。これにより、本来共通化すべき設定が分散してしまいます。
課題
背景で述べた問題は、実際の開発現場で以下のような具体的な課題として現れています。
設定の一貫性保持の困難
複数のパッケージで異なる設定値が使われることで、予期しない動作が発生します。
型チェックの厳密さにばらつきが生じる
あるパッケージでは strict: true
を使用し、別のパッケージでは strict: false
を使用している場合、同じコードでも型エラーの検出レベルが異なります。これにより、統合時に予期しない型エラーが発生することがあります。
typescript// Package A (strict: true)
function processUser(user: User | null) {
return user.name; // エラー: Object is possibly 'null'
}
// Package B (strict: false)
function processUser(user: User | null) {
return user.name; // エラーなし(実行時にランタイムエラーの可能性)
}
ターゲット環境の不整合
target
や module
の設定が異なることで、出力される JavaScript コードの互換性に問題が生じます。例えば、一部のパッケージが ES5
をターゲットにし、他が ES2020
をターゲットにしている場合、統合後のコードで動作環境の制約が不明確になります。
パッケージ間の設定差異によるトラブル
設定の違いが原因で発生する、デバッグが困難な問題について説明します。
パッケージ間での設定差異が引き起こす問題の流れを図で示します。
mermaidsequenceDiagram
participant Dev as 開発者
participant PkgA as パッケージA
participant PkgB as パッケージB
participant Build as ビルドシステム
Dev->>PkgA: コード作成
Dev->>PkgB: 同様のコード作成
Note over PkgA: strict: true<br/>target: ES2020
Note over PkgB: strict: false<br/>target: ES5
PkgA->>Build: ビルド成功
PkgB->>Build: ビルド成功
Build->>Dev: 統合時にエラー
Note over Dev: 設定差異の特定に<br/>時間を要する
図で理解できる要点:
- 個別パッケージでは正常動作するコード
- 統合時に発生する予期しないエラー
- 設定差異の特定とデバッグの複雑さ
モジュール解決の不整合
moduleResolution
の設定が異なると、同じ import 文でも異なるモジュールを参照する可能性があります。これは特にモノレポ環境で深刻な問題となります。
出力ディレクトリ構造のばらつき
outDir
や rootDir
の設定が統一されていない場合、ビルド後のファイル配置が予測しにくくなり、デプロイメント時に問題となることがあります。
設定変更時の影響範囲拡大
TypeScript 設定の変更が必要になった際の課題について詳しく見ていきましょう。
全パッケージへの変更適用コスト 新しい TypeScript 機能を活用するために設定変更が必要な場合、全てのパッケージで同じ変更を行う必要があります。パッケージ数が多いほど、この作業は煩雑になります。
例えば、useDefineForClassFields
を有効にしたい場合:
typescript// 変更前(各パッケージで個別に設定)
// packages/api/tsconfig.json, packages/web/tsconfig.json, packages/shared/tsconfig.json...
{
"compilerOptions": {
// ... 他の設定
}
}
typescript// 変更後(各パッケージで個別に追加)
{
"compilerOptions": {
// ... 他の設定
"useDefineForClassFields": true
}
}
設定ミスによる部分的な問題 手動での設定変更では、一部のパッケージで設定ミスや更新漏れが発生しやすくなります。これにより、プロジェクト全体で不整合が生じ、原因の特定に時間がかかります。
バージョン管理での追跡困難 複数ファイルでの同時変更は、Git の diff や Pull Request での変更内容把握を困難にします。レビュー時に設定変更の意図や影響範囲を正確に理解することが難しくなります。
解決策
これまで述べた課題を解決するための効果的なアプローチがあります。それが共有可能な tsconfig 設計です。
tsconfig/bases による共有設定
@tsconfig/bases
パッケージは、よく使用される TypeScript 設定のプリセットを提供する Microsoft 公式のパッケージです。
@tsconfig/bases の仕組み このパッケージには、異なる実行環境やフレームワーク向けの最適化された設定が含まれています。
bash# パッケージのインストール
yarn add -D @tsconfig/node16 @tsconfig/react17
基本的な使用方法は以下のようになります:
typescript// packages/api/tsconfig.json
{
"extends": "@tsconfig/node16/tsconfig.json",
"compilerOptions": {
// プロジェクト固有の設定のみを記述
"outDir": "./dist",
"rootDir": "./src"
}
}
この方法により、基本設定は @tsconfig/node16
から継承し、パッケージ固有の設定のみを個別に定義できます。
利用可能なプリセット一覧 主要な実行環境向けのプリセットが用意されています:
プリセット | 用途 | 主な設定 |
---|---|---|
@tsconfig/node16 | Node.js 16+ 環境 | target: ES2021, module: commonjs |
@tsconfig/node18 | Node.js 18+ 環境 | target: ES2022, module: commonjs |
@tsconfig/react17 | React 17 環境 | jsx: react-jsx, lib: DOM |
@tsconfig/next | Next.js 環境 | Next.js 最適化設定 |
@tsconfig/vite | Vite 環境 | ESM とバンドル最適化 |
継承ベースの設計アプローチ
TypeScript の設定継承を活用して、段階的な設定管理を行います。
継承ベースの設定管理構造を図で示します。
mermaidflowchart TB
base["@tsconfig/bases<br/>(公式プリセット)"] --> common[プロジェクト共通設定<br/>tsconfig.base.json]
common --> node_base[Node.js 基本設定<br/>tsconfig.node.json]
common --> web_base[Web 基本設定<br/>tsconfig.web.json]
node_base --> api[API パッケージ<br/>packages/api/tsconfig.json]
node_base --> worker[Worker パッケージ<br/>packages/worker/tsconfig.json]
web_base --> frontend[Frontend パッケージ<br/>packages/web/tsconfig.json]
web_base --> mobile[Mobile パッケージ<br/>packages/mobile/tsconfig.json]
style base fill:#e1f5fe
style common fill:#f3e5f5
style node_base fill:#fff3e0
style web_base fill:#fff3e0
style api fill:#e8f5e8
style worker fill:#e8f5e8
style frontend fill:#e8f5e8
style mobile fill:#e8f5e8
図で理解できる要点:
- 公式プリセットからプロジェクト独自設定への段階的継承
- 環境タイプ別の中間設定層による効率的な管理
- 各パッケージは最小限の固有設定のみを持つ構造
段階的継承の実装例 プロジェクト共通設定から始まり、環境別、パッケージ別へと段階的に継承を行います:
typescript// tsconfig.base.json(プロジェクト共通設定)
{
"extends": "@tsconfig/node16/tsconfig.json",
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true
}
}
typescript// tsconfig.web.json(Web系共通設定)
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"jsx": "react-jsx",
"lib": ["DOM", "DOM.Iterable"],
"moduleResolution": "node"
}
}
パッケージタイプ別最適化
異なる用途のパッケージに対して、それぞれに最適化された設定を用意します。
API サービス向け最適化 サーバーサイド処理に特化した設定を行います:
typescript// tsconfig.api.json
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"module": "commonjs",
"target": "ES2020",
"lib": ["ES2020"],
"types": ["node"],
"moduleResolution": "node",
"allowSyntheticDefaultImports": true
}
}
React アプリケーション向け最適化 フロントエンド開発に最適化された設定を行います:
typescript// tsconfig.react.json
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"module": "esnext",
"target": "ES2020",
"lib": ["DOM", "DOM.Iterable", "ES2020"],
"jsx": "react-jsx",
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"isolatedModules": true
}
}
ライブラリパッケージ向け最適化 再利用可能なライブラリ作成に適した設定を行います:
typescript// tsconfig.library.json
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"module": "esnext",
"target": "ES5",
"lib": ["ES2015"],
"declaration": true,
"declarationMap": true,
"outDir": "./dist",
"rootDir": "./src"
}
}
この段階的な設定継承により、以下のメリットを得られます:
- 設定の一元管理: 共通設定の変更が全パッケージに自動で反映される
- 環境別最適化: 各パッケージタイプに応じた最適な設定を維持
- メンテナンス性向上: 設定変更時の作業範囲を大幅に削減
- 設定意図の明確化: 継承関係により設定の目的と影響範囲が明確になる
具体例
理論から実践へと移り、実際のプロジェクトでの共有設定実装例を詳しく見ていきます。
基本的な共有設定の作成
まずは最もシンプルな共有設定から始めて、段階的に構築していきましょう。
Step 1: プロジェクト構造の準備
一般的なモノレポ構造を想定した設定を作成します:
bash# プロジェクト構造の確認
my-project/
├── packages/
│ ├── api/ # Node.js API サーバー
│ ├── web/ # React フロントエンド
│ └── shared/ # 共有ライブラリ
├── tsconfig.base.json # プロジェクト基本設定
├── tsconfig.node.json # Node.js 用設定
├── tsconfig.react.json # React 用設定
└── package.json
Step 2: 基本設定ファイルの作成
プロジェクト全体で共通する基本設定を定義します:
typescript// tsconfig.base.json
{
"extends": "@tsconfig/node16/tsconfig.json",
"compilerOptions": {
// 型チェック強化
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
// インポート解決
"moduleResolution": "node",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
// 出力設定
"declaration": true,
"declarationMap": true,
"sourceMap": true,
// その他便利な設定
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"exclude": [
"node_modules",
"dist",
"build",
"**/*.test.ts",
"**/*.spec.ts"
]
}
Step 3: 環境別設定の作成
Node.js 環境向けの設定を作成します:
typescript// tsconfig.node.json
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"module": "commonjs",
"target": "ES2020",
"lib": ["ES2020"],
"types": ["node"],
"outDir": "./dist",
"rootDir": "./src",
// Node.js 特有の設定
"resolveJsonModule": true,
"allowJs": false
}
}
React 環境向けの設定を作成します:
typescript// tsconfig.react.json
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"module": "esnext",
"target": "ES2020",
"lib": ["DOM", "DOM.Iterable", "ES2020"],
// React 特有の設定
"jsx": "react-jsx",
"isolatedModules": true,
// バンドラー向け設定
"noEmit": true,
"allowJs": true,
"resolveJsonModule": true
}
}
Step 4: パッケージ固有設定の作成
各パッケージでは、環境別設定を継承し最小限の設定のみを行います:
typescript// packages/api/tsconfig.json
{
"extends": "../../tsconfig.node.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src"
},
"include": [
"src/**/*"
],
"exclude": [
"src/**/*.test.ts",
"src/**/*.spec.ts"
]
}
typescript// packages/web/tsconfig.json
{
"extends": "../../tsconfig.react.json",
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"@/*": ["./*"],
"@/components/*": ["./components/*"]
}
},
"include": [
"src/**/*",
"public/**/*"
]
}
typescript// packages/shared/tsconfig.json
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"module": "esnext",
"target": "ES2015",
"outDir": "./dist",
"rootDir": "./src",
// ライブラリ向け設定
"declaration": true,
"declarationMap": true
},
"include": [
"src/**/*"
]
}
Step 5: パッケージマネージャー設定
必要な依存関係をインストールします:
json// package.json
{
"devDependencies": {
"@tsconfig/node16": "^1.0.0",
"typescript": "^4.9.0"
}
}
これで基本的な共有設定の構築が完了しました。各パッケージは必要最小限の設定のみを持ち、共通設定は一元管理されています。
モノレポでの活用パターン
実際のモノレポ環境では、より複雑な要件に対応する必要があります。実用的なパターンを見ていきましょう。
大規模モノレポでの設定例
多数のパッケージを含む実際のプロジェクト構造を想定してみます:
bash# より大規模な構造例
enterprise-project/
├── config/
│ └── typescript/
│ ├── tsconfig.base.json
│ ├── tsconfig.node.json
│ ├── tsconfig.react.json
│ ├── tsconfig.nextjs.json
│ └── tsconfig.library.json
├── packages/
│ ├── backend/
│ │ ├── api-server/ # Express API
│ │ ├── worker-service/ # バックグラウンドワーカー
│ │ └── auth-service/ # 認証サービス
│ ├── frontend/
│ │ ├── admin-panel/ # 管理画面 (React)
│ │ ├── user-app/ # ユーザー向けアプリ (Next.js)
│ │ └── mobile-app/ # モバイルアプリ (React Native)
│ └── shared/
│ ├── ui-components/ # UI コンポーネント
│ ├── utils/ # ユーティリティ
│ └── types/ # 型定義
└── tools/
└── build-scripts/ # ビルドスクリプト
設定ファイルの詳細実装
各環境に特化した設定の詳細を見てみましょう:
typescript// config/typescript/tsconfig.base.json
{
"extends": "@tsconfig/node16/tsconfig.json",
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
// パス解決設定(モノレポ用)
"baseUrl": ".",
"paths": {
"@shared/ui/*": ["packages/shared/ui-components/src/*"],
"@shared/utils/*": ["packages/shared/utils/src/*"],
"@shared/types/*": ["packages/shared/types/src/*"]
}
}
}
typescript// config/typescript/tsconfig.nextjs.json
{
"extends": "./tsconfig.react.json",
"compilerOptions": {
"target": "ES2017",
"lib": ["DOM", "DOM.Iterable", "ES6"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
// Next.js 特有の設定
"incremental": true,
"plugins": [
{
"name": "next"
}
]
}
}
各パッケージでの設定適用例
バックエンドサービスの設定:
typescript// packages/backend/api-server/tsconfig.json
{
"extends": "../../../config/typescript/tsconfig.node.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src",
"baseUrl": "./src",
"paths": {
"@/*": ["./*"],
"@shared/*": ["../../../packages/shared/*/src"]
}
},
"include": [
"src/**/*"
],
"exclude": [
"src/**/*.test.ts",
"src/**/*.spec.ts",
"dist"
]
}
Next.js アプリケーションの設定:
typescript// packages/frontend/user-app/tsconfig.json
{
"extends": "../../../config/typescript/tsconfig.nextjs.json",
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
"@/components/*": ["./src/components/*"],
"@shared/*": ["../../shared/*/src/*"]
}
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts"
],
"exclude": [
"node_modules"
]
}
ワークスペース設定の連携
Yarn ワークスペースと連携した設定管理:
json// package.json (ルート)
{
"name": "enterprise-project",
"private": true,
"workspaces": [
"packages/backend/*",
"packages/frontend/*",
"packages/shared/*"
],
"devDependencies": {
"@tsconfig/node16": "^1.0.0",
"@tsconfig/react17": "^1.0.0",
"typescript": "^4.9.0"
},
"scripts": {
"type-check": "yarn workspaces foreach -A run type-check",
"type-check:watch": "yarn workspaces foreach -A -j unlimited run type-check:watch"
}
}
各パッケージで共通のスクリプトを定義:
json// packages/backend/api-server/package.json
{
"name": "@enterprise/api-server",
"scripts": {
"type-check": "tsc --noEmit",
"type-check:watch": "tsc --noEmit --watch",
"build": "tsc",
"dev": "ts-node-dev src/index.ts"
}
}
モノレポでの活用における詳細な設定管理のフローを図で示します。
mermaidflowchart TD
workspace[Yarn/NPM ワークスペース] --> config_dir[config/typescript/ 設定ディレクトリ]
config_dir --> base_config[tsconfig.base.json<br/>共通基本設定]
config_dir --> env_configs[環境別設定ファイル群]
env_configs --> node_config[tsconfig.node.json]
env_configs --> react_config[tsconfig.react.json]
env_configs --> nextjs_config[tsconfig.nextjs.json]
env_configs --> lib_config[tsconfig.library.json]
node_config --> backend_packages[Backend パッケージ群]
react_config --> react_packages[React パッケージ群]
nextjs_config --> nextjs_packages[Next.js パッケージ群]
lib_config --> shared_packages[共有ライブラリ群]
backend_packages --> api[API Server]
backend_packages --> worker[Worker Service]
backend_packages --> auth[Auth Service]
react_packages --> admin[Admin Panel]
react_packages --> mobile[Mobile App]
nextjs_packages --> user_app[User App]
shared_packages --> ui_lib[UI Components]
shared_packages --> utils_lib[Utils Library]
shared_packages --> types_lib[Types Library]
style workspace fill:#e1f5fe
style config_dir fill:#f3e5f5
style base_config fill:#fff3e0
style env_configs fill:#fff3e0
図で理解できる要点:
- ワークスペースレベルでの一元的な設定管理
- 設定ディレクトリによる整理された構造
- パッケージタイプごとの最適化された継承チェーン
環境別設定の継承設計
開発・テスト・本番環境それぞれに最適化された設定を継承チェーンで管理する方法を説明します。
環境別設定の必要性
実際のプロジェクトでは、環境によって異なる TypeScript 設定が必要になることがあります:
- 開発環境: 高速なコンパイル、詳細なエラー情報、ソースマップ
- テスト環境: テストフレームワークとの互換性、モック対応
- 本番環境: 最適化されたビルド、最小限の出力ファイル
段階的継承による環境設定
環境別の設定を段階的に継承することで、効率的な管理を実現できます:
typescript// tsconfig.base.json(全環境共通)
{
"extends": "@tsconfig/node16/tsconfig.json",
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"moduleResolution": "node",
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
typescript// tsconfig.development.json(開発環境)
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"sourceMap": true,
"inlineSourceMap": false,
"declaration": true,
"declarationMap": true,
// 開発効率向上のための設定
"incremental": true,
"tsBuildInfoFile": "./node_modules/.cache/typescript/tsconfig.tsbuildinfo",
// 詳細なエラー情報
"noErrorTruncation": true,
"preserveWatchOutput": true
}
}
typescript// tsconfig.test.json(テスト環境)
{
"extends": "./tsconfig.development.json",
"compilerOptions": {
"types": ["node", "jest", "@testing-library/jest-dom"],
// テスト用設定
"allowJs": true,
"esModuleInterop": true,
"isolatedModules": false,
// テスト環境用のパス解決
"paths": {
"@/*": ["./src/*"],
"@test/*": ["./test/*"],
"@mocks/*": ["./test/mocks/*"]
}
},
"include": [
"src/**/*",
"test/**/*",
"**/*.test.ts",
"**/*.spec.ts"
]
}
typescript// tsconfig.production.json(本番環境)
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"sourceMap": false,
"declaration": false,
"declarationMap": false,
// 本番最適化設定
"removeComments": true,
"noEmitOnError": true,
// 出力最適化
"target": "ES2018",
"module": "commonjs"
},
"exclude": [
"**/*.test.ts",
"**/*.spec.ts",
"test/**/*",
"**/*.stories.ts"
]
}
ビルドスクリプトとの連携
異なる環境設定を使い分けるためのスクリプト例:
json// package.json
{
"scripts": {
"dev": "ts-node-dev --project tsconfig.development.json src/index.ts",
"build": "tsc --project tsconfig.production.json",
"build:dev": "tsc --project tsconfig.development.json",
"test": "jest --config jest.config.js",
"type-check": "tsc --project tsconfig.test.json --noEmit",
"type-check:prod": "tsc --project tsconfig.production.json --noEmit"
}
}
Docker 環境との統合
コンテナ環境で環境別設定を活用する例:
dockerfile# Dockerfile.development
FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
COPY yarn.lock ./
RUN yarn install
COPY . .
# 開発環境用のTypeScript設定でビルド
RUN yarn build:dev
CMD ["yarn", "dev"]
dockerfile# Dockerfile.production
FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
COPY yarn.lock ./
# 本番用依存関係のみインストール
RUN yarn install --frozen-lockfile --production=false
COPY . .
# 本番環境用設定でビルド
RUN yarn build
# 不要なファイルを削除してイメージサイズを削減
RUN yarn install --production && yarn cache clean
RUN rm -rf src/ test/ *.config.js tsconfig.*.json
CMD ["node", "dist/index.js"]
CI/CD パイプラインでの活用
GitHub Actions での環境別設定使用例:
yaml# .github/workflows/ci.yml
name: CI/CD Pipeline
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '16'
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Type check (test environment)
run: yarn type-check
- name: Run tests
run: yarn test
build-production:
runs-on: ubuntu-latest
needs: test
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Type check (production)
run: yarn type-check:prod
- name: Build for production
run: yarn build
- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: production-build
path: dist/
環境別設定の継承関係と利用場面を図で示します。
mermaidstateDiagram-v2
[*] --> BaseConfig: プロジェクト基本設定
BaseConfig --> DevConfig: 開発環境設定
BaseConfig --> ProdConfig: 本番環境設定
DevConfig --> TestConfig: テスト環境設定
DevConfig --> DevBuild: 開発ビルド
TestConfig --> TestExecution: テスト実行
ProdConfig --> ProdBuild: 本番ビルド
DevBuild --> LocalDev: ローカル開発
TestExecution --> CI_CD: CI/CD パイプライン
ProdBuild --> Deployment: デプロイメント
note right of BaseConfig
strict: true
共通型チェック設定
end note
note right of DevConfig
sourceMap: true
incremental: true
開発効率重視
end note
note right of TestConfig
jest types included
test paths configured
end note
note right of ProdConfig
removeComments: true
最適化設定
end note
図で理解できる要点:
- 基本設定から環境別設定への段階的継承
- 各環境の目的に応じた最適化設定
- 開発フロー全体での設定活用パターン
まとめ
本記事では、TypeScript プロジェクトにおける設定管理の課題から、@tsconfig/bases
を活用した共有可能な設定設計まで詳しく解説してきました。
実現できる主なメリット
設定管理の効率化 従来の個別設定管理から共有ベース設定への移行により、メンテナンス作業を大幅に削減できます。TypeScript 設定の変更が必要な場合も、基本設定ファイルの更新だけで全パッケージに反映されるため、作業時間の短縮とミスの軽減が実現できます。
プロジェクト全体での一貫性確保 継承ベースの設計により、全パッケージで一貫した型チェックレベルやコンパイル設定を維持できます。これにより、パッケージ間での統合時に発生する予期しないエラーを防ぐことができます。
環境別最適化の実現 開発・テスト・本番環境それぞれに最適化された設定を、継承チェーンで効率的に管理できます。環境固有の要件に応じてカスタマイズしながら、共通設定は一元管理されます。
チーム開発での生産性向上 設定の意図や継承関係が明確になることで、新しいチームメンバーでも設定を理解しやすくなります。また、設定変更時の影響範囲が予測しやすく、安全な変更が可能になります。
導入時の推奨アプローチ
段階的な導入 既存のプロジェクトに導入する場合は、まず一つのパッケージで共有設定を試験導入し、効果を確認してから他のパッケージに展開することを推奨します。
チーム内での合意形成 設定変更はチーム全体に影響するため、導入前にチームメンバーと設計方針について合意を取ることが重要です。継承関係や命名規則について統一見解を持つことで、より効果的な活用が可能になります。
継続的な改善
プロジェクトの成長に応じて設定も進化させていく必要があります。定期的に設定の見直しを行い、新しい TypeScript 機能や@tsconfig/bases
の更新に合わせて最適化を継続しましょう。
今後の活用に向けて
共有可能な tsconfig 設計は、プロジェクトの規模が大きくなるほどその効果を発揮します。モノレポ環境での活用はもちろん、複数のプロジェクト間でも設定パターンを共有することで、組織全体での TypeScript 活用レベルを向上させることができます。
TypeScript エコシステムは今後も進化し続けるため、共有設定アプローチを採用することで、新機能への対応やベストプラクティスの適用もより容易になるでしょう。
本記事で紹介した設計パターンを参考に、あなたのプロジェクトに最適な共有設定を構築してみてください。効率的な設定管理により、より生産的な TypeScript 開発を実現できるはずです。
関連リンク
- article
TypeScript 共有可能な tsconfig 設計:`tsconfig/bases`で複数パッケージを一括最適化
- article
TypeScript ランタイム検証ライブラリ比較:Zod / Valibot / typia / io-ts の選び方
- article
【解決策】TypeScript TS2307「Cannot find module…」が出る本当の原因と最短復旧手順
- article
Astro × TypeScript:型安全な静的サイト開発入門
- article
Pinia × TypeScript:型安全なストア設計入門
- article
TypeScript で実現するクリーンアーキテクチャ:層分離と依存性逆転の実践
- article
MySQL Optimizer Hints 実測比較:INDEX_MERGE/NO_RANGE_OPTIMIZATION ほか
- article
Zustand × TanStack Query × SWR:キャッシュ・再検証・型安全の実運用比較
- article
Motion(旧 Framer Motion) vs CSS Transition/WAAPI:可読性・制御性・性能を実測比較
- article
WordPress 情報設計:CPT/タクソノミー/メタデータの設計指針
- article
WebSocket vs WebTransport vs SSE 徹底比較:遅延・帯域・安定性を実測レビュー
- article
JavaScript OffscreenCanvas 検証:Canvas/OffscreenCanvas/WebGL の速度比較
- blog
iPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
- blog
Googleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
- blog
【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
- blog
Googleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
- blog
Pixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
- blog
フロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
- review
今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
- review
ついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
- review
愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
- review
週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
- review
新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
- review
科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来