# ⚡ ビルドシステム GitHub Power Scouterのビルドシステム(Vite)の詳細解説です。初心者からベテランまで、ビルドシステムの理解と最適化について包括的に説明します。 ## 🏗️ Viteビルドシステム概要 ```mermaid flowchart TD A[Source Code] --> B{Development Mode?} B -->|Yes| C[Vite Dev Server] B -->|No| D[Production Build] C --> E[ES Modules] C --> F[HMR] C --> G[Fast Refresh] D --> H[Bundle Analysis] D --> I[Code Splitting] D --> J[Asset Optimization] H --> K[Rollup] I --> K J --> K K --> L[Optimized Assets] L --> M[Static Files] ``` ## 🎯 Viteが選ばれる理由 ### 従来ツールとの比較 | 特徴 | Webpack | Parcel | Vite | 優位性 | |------|---------|--------|------|--------| | **開発サーバー起動** | 10-30秒 | 5-15秒 | 0.5-2秒 | ✅ 10-50倍高速 | | **HMR** | 1-5秒 | 1-3秒 | 0.1-0.5秒 | ✅ 瞬時更新 | | **学習コスト** | 高 | 中 | 低 | ✅ 簡単設定 | | **エコシステム** | 最大 | 中 | 成長中 | ⚠️ まだ発展途上 | ### Viteのアーキテクチャ ```mermaid graph LR subgraph "Development" A[Source Files] --> B[esbuild Transform] B --> C[ES Modules] C --> D[Browser] end subgraph "Production" E[Source Files] --> F[Rollup Bundle] F --> G[Optimized Bundle] G --> H[Static Assets] end ``` ## 🔧 設定ファイル詳細 ### vite.config.ts 完全解説 ```typescript import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import { resolve } from 'path' export default defineConfig({ // プラグイン設定 plugins: [ react({ // React Fast Refresh設定 fastRefresh: true, // JSX運用ランタイム設定 jsxRuntime: 'automatic', }), ], // 開発サーバー設定 server: { port: 5173, host: true, // ネットワークアクセス許可 open: true, // ブラウザ自動オープン cors: true, // CORS設定 proxy: { // APIプロキシ設定(開発時のCORS回避) '/api': { target: 'https://api.github.com', changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, ''), }, }, }, // ビルド設定 build: { // 出力ディレクトリ outDir: 'dist', // アセットディレクトリ assetsDir: 'assets', // ソースマップ生成 sourcemap: process.env.NODE_ENV !== 'production', // minify設定 minify: 'terser', terserOptions: { compress: { drop_console: true, // console.log削除 drop_debugger: true, // debugger文削除 }, }, // チャンク分割設定 rollupOptions: { output: { manualChunks: { // ベンダーチャンク vendor: ['react', 'react-dom'], // ユーティリティチャンク utils: ['./src/utils/index.ts'], }, // アセット命名規則 assetFileNames: (assetInfo) => { const info = assetInfo.name.split('.') const ext = info[info.length - 1] // 画像ファイル if (/\.(png|jpe?g|svg|gif|tiff|bmp|ico)$/i.test(assetInfo.name)) { return `images/[name]-[hash][extname]` } // フォントファイル if (/\.(woff2?|eot|ttf|otf)$/i.test(assetInfo.name)) { return `fonts/[name]-[hash][extname]` } return `${ext}/[name]-[hash][extname]` }, // JSファイル命名規則 chunkFileNames: 'js/[name]-[hash].js', entryFileNames: 'js/[name]-[hash].js', }, }, // ファイルサイズ警告しきい値 chunkSizeWarningLimit: 1000, // 1MB }, // ベースパス設定(デプロイ先に応じて変更) base: process.env.NODE_ENV === 'production' ? '/programming-skill-scouter/' // GitHub Pages : './', // 解決設定 resolve: { alias: { '@': resolve(__dirname, 'src'), '@components': resolve(__dirname, 'src/components'), '@types': resolve(__dirname, 'src/types'), '@utils': resolve(__dirname, 'src/utils'), }, }, // CSS設定 css: { modules: { localsConvention: 'camelCase', }, preprocessorOptions: { scss: { additionalData: `@import "@/styles/variables.scss";`, }, }, }, // 環境変数設定 define: { __APP_VERSION__: JSON.stringify(process.env.npm_package_version), __BUILD_TIME__: JSON.stringify(new Date().toISOString()), }, }) ``` ## 🚀 npm スクリプト詳細 ### package.json scripts ```json { "scripts": { // 開発サーバー起動 "dev": "vite", "dev:host": "vite --host", // ネットワークアクセス有効 "dev:debug": "vite --debug", // デバッグモード // ビルド関連 "build": "tsc -b && vite build", "build:analyze": "npm run build && npx vite-bundle-analyzer dist", "build:preview": "npm run build && npm run preview", // 型チェック "type-check": "tsc --noEmit", "type-check:watch": "tsc --noEmit --watch", // リント・フォーマット "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "lint:fix": "eslint . --ext ts,tsx --fix", "format": "prettier --write \"src/**/*.{ts,tsx}\"", "format:check": "prettier --check \"src/**/*.{ts,tsx}\"", // プレビュー "preview": "vite preview", "preview:host": "vite preview --host", // デプロイ "predeploy": "npm run build", "deploy": "gh-pages -d dist", // クリーンアップ "clean": "rm -rf dist node_modules/.vite", "fresh": "npm run clean && npm install" } } ``` ### スクリプト実行例 ```bash # 開発環境での作業フロー npm run dev # 開発サーバー起動 npm run type-check # 型チェック npm run lint # リント実行 npm run format # コードフォーマット # ビルド・デプロイフロー npm run build # プロダクションビルド npm run build:analyze # バンドル分析 npm run preview # ビルド結果プレビュー npm run deploy # デプロイ ``` ## 📊 バンドル最適化 ### コード分割戦略 ```mermaid graph TD A[Application Bundle] --> B[Entry Chunk] A --> C[Vendor Chunk] A --> D[Utils Chunk] A --> E[Dynamic Chunks] B --> F[App.tsx] B --> G[main.tsx] C --> H[react] C --> I[react-dom] D --> J[API utilities] D --> K[Helper functions] E --> L[Lazy Components] E --> M[Route Components] ``` ### 動的インポートの実装 ```typescript // コンポーネントの遅延読み込み import { lazy, Suspense } from 'react' // 動的インポート const ResumeModal = lazy(() => import('./ResumeModal')) const HeavyComponent = lazy(() => import('./HeavyComponent').then(module => ({ default: module.HeavyComponent })) ) // 使用例 function App() { return ( Loading...}> ) } ``` ### Tree Shaking最適化 ```typescript // ❌ 悪い例: ライブラリ全体をインポート import * as utils from 'lodash' // ✅ 良い例: 必要な関数のみインポート import { debounce, throttle } from 'lodash' // ✅ さらに良い例: 個別モジュールインポート import debounce from 'lodash/debounce' import throttle from 'lodash/throttle' ``` ## 🔍 バンドル分析 ### バンドルサイズ分析ツール ```bash # vite-bundle-analyzerでの分析 npm install --save-dev vite-bundle-analyzer npx vite-bundle-analyzer dist # rollup-plugin-visualizerでの分析 npm install --save-dev rollup-plugin-visualizer npm run build ``` ### 分析結果の読み方 ```mermaid pie title Bundle Size Distribution "React & ReactDOM" : 45 "Application Code" : 30 "Third-party Libraries" : 15 "CSS & Assets" : 10 ``` ### 最適化指標 | メトリクス | 目標値 | 現在値 | 状態 | |------------|--------|--------|------| | **Total Bundle Size** | < 1MB | ~220KB | ✅ | | **Initial JS** | < 500KB | ~205KB | ✅ | | **CSS** | < 100KB | ~7KB | ✅ | | **Vendor Chunk** | < 200KB | ~12KB | ✅ | | **Gzip Compression** | < 70% | ~65% | ✅ | ## ⚙️ 開発時最適化 ### HMR(Hot Module Replacement)設定 ```typescript // HMRのカスタマイズ if (import.meta.hot) { // モジュール受け入れ設定 import.meta.hot.accept() // データ保持設定 import.meta.hot.accept(['./UserData'], (newModule) => { // 状態を保持しながらモジュール更新 }) // 破棄時のクリーンアップ import.meta.hot.dispose(() => { // クリーンアップ処理 }) } ``` ### 開発時専用機能 ```typescript // 開発時のみ有効なデバッグ機能 if (import.meta.env.DEV) { // React DevTools window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = window.__REACT_DEVTOOLS_GLOBAL_HOOK__ || {}; // パフォーマンス測定 console.time('Component Render') // API レスポンス時間測定 const startTime = performance.now() } ``` ## 🚀 プロダクションビルド最適化 ### アセット最適化 ```typescript // vite.config.ts での画像最適化 import { defineConfig } from 'vite' export default defineConfig({ build: { rollupOptions: { external: [ // 外部依存として扱うライブラリ ], output: { // 画像の最適化 assetFileNames: (assetInfo) => { if (/\.(png|jpe?g|svg|gif)$/i.test(assetInfo.name)) { return 'images/[name]-[hash][extname]' } return 'assets/[name]-[hash][extname]' } } } }, // アセット処理設定 assetsInclude: ['**/*.md'], // Markdownファイルをアセットとして処理 }) ``` ### 圧縮設定 ```typescript // Gzip/Brotli圧縮 import { defineConfig } from 'vite' import { compression } from 'vite-plugin-compression' export default defineConfig({ plugins: [ compression({ algorithm: 'gzip', threshold: 1024, // 1KB以上のファイルを圧縮 }), compression({ algorithm: 'brotliCompress', ext: '.br', threshold: 1024, }), ], }) ``` ## 🔧 カスタムプラグイン ### GitHub APIキャッシュプラグイン ```typescript // plugins/github-cache.ts import type { Plugin } from 'vite' export function githubCachePlugin(): Plugin { return { name: 'github-cache', configureServer(server) { server.middlewares.use('/api/github', (req, res, next) => { // GitHub APIレスポンスのキャッシュ処理 const cacheKey = req.url // キャッシュから取得を試行 const cached = getCache(cacheKey) if (cached) { res.setHeader('Content-Type', 'application/json') res.end(JSON.stringify(cached)) return } next() }) }, } } ``` ### ビルド時処理プラグイン ```typescript // plugins/build-info.ts import type { Plugin } from 'vite' export function buildInfoPlugin(): Plugin { return { name: 'build-info', generateBundle() { // ビルド情報をJSONファイルとして出力 const buildInfo = { timestamp: new Date().toISOString(), version: process.env.npm_package_version, environment: process.env.NODE_ENV, } this.emitFile({ type: 'asset', fileName: 'build-info.json', source: JSON.stringify(buildInfo, null, 2), }) }, } } ``` ## 📈 パフォーマンス監視 ### ビルド時間監視 ```typescript // plugins/build-timer.ts import type { Plugin } from 'vite' export function buildTimerPlugin(): Plugin { let startTime: number return { name: 'build-timer', buildStart() { startTime = Date.now() console.log('🚀 Build started...') }, generateBundle() { const duration = Date.now() - startTime console.log(`✅ Build completed in ${duration}ms`) }, } } ``` ### バンドルサイズ監視 ```bash # size-limit での監視 npm install --save-dev size-limit @size-limit/preset-big-lib # package.json { "size-limit": [ { "path": "dist/assets/*.js", "limit": "500 KB" }, { "path": "dist/assets/*.css", "limit": "50 KB" } ] } ``` ## 🚨 トラブルシューティング ### よくある問題と解決方法 #### 1. ビルドが遅い ```bash # 並列処理の有効化 export VITE_BUILD_THREADS=$(nproc) # キャッシュのクリア rm -rf node_modules/.vite npm run build ``` #### 2. メモリ不足エラー ```bash # Node.jsのメモリ制限を増加 export NODE_OPTIONS="--max-old-space-size=4096" npm run build ``` #### 3. アセットが読み込めない ```typescript // 正しい相対パス設定 export default defineConfig({ base: process.env.NODE_ENV === 'production' ? '/your-repo-name/' : './', }) ``` ## 📊 CI/CD統合 ### GitHub Actions設定 ```yaml # .github/workflows/build.yml name: Build and Test on: [push, pull_request] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' - name: Install dependencies run: npm ci - name: Type check run: npm run type-check - name: Lint run: npm run lint - name: Build run: npm run build - name: Size check run: npx size-limit - name: Upload build artifacts uses: actions/upload-artifact@v4 with: name: build-files path: dist/ ``` ## 🔮 将来の最適化 ### 次世代ツールへの移行計画 ```mermaid timeline title Build Tool Evolution Current : Vite 7.0 : esbuild : Rollup Q2 2024 : Vite 8.0 : Rollup 5.0 : Lightning CSS Q4 2024 : Native ESM : Import Maps : Web Assembly 2025 : Rust-based tools : Even faster builds : Zero-config setup ``` --- **次のステップ**: [リント・フォーマットガイド](Linting-and-Formatting.md)でコード品質管理を学びましょう。