T-CREATOR

Turbopack のトラブルシュート:よくある問題と解決策

Turbopack のトラブルシュート:よくある問題と解決策

開発の現場で Turbopack を使い始めたものの、思わぬエラーに遭遇して困った経験はありませんか?

「ビルドが通らない」「開発サーバーが起動しない」「ホットリロードが効かない」など、Turbopack 特有の問題に直面すると、開発効率が大きく下がってしまいます。

この記事では、Turbopack でよく発生する問題とその解決策を、実際のエラーコードとともに詳しく解説します。問題解決のコツを身につけて、スムーズな開発環境を構築しましょう。

Turbopack とは

Turbopack は、Vercel が開発した次世代の JavaScript バンドラーです。Rust で書かれており、Webpack の後継として設計されています。

Turbopack の特徴

  • 高速なビルド: インクリメンタルコンパイルにより、変更箇所のみを再ビルド
  • メモリ効率: より少ないメモリ使用量で大規模プロジェクトを処理
  • 開発サーバー: 高速なホットリロード機能
  • Next.js 統合: Next.js 13 以降でデフォルトのバンドラーとして採用

従来の Webpack との違い

項目WebpackTurbopack
言語JavaScriptRust
ビルド速度標準10-700 倍高速
メモリ使用量多い少ない
開発サーバー起動遅い高速

よくある問題と解決策

ビルドエラーが発生する場合

エラー 1: Module not found

最も頻繁に発生するエラーの一つです。モジュールのパスが正しく解決されていない場合に発生します。

bashError: Cannot find module './components/Button'
Module not found: Can't resolve './components/Button' in '/app/src'

解決策

まず、ファイルの存在を確認します:

bash# ファイルの存在確認
ls -la src/components/Button.tsx
ls -la src/components/Button.jsx
ls -la src/components/Button/index.tsx

次に、インポート文を修正します:

typescript// 修正前
import Button from './components/Button';

// 修正後(拡張子を明示)
import Button from './components/Button.tsx';
// または
import Button from './components/Button/index.tsx';

エラー 2: TypeScript 型エラー

TypeScript の型チェックでエラーが発生する場合です。

bashType error: Property 'name' does not exist on type 'User | null'
Type error: Cannot find type definition file for 'react'

解決策

TypeScript の設定を確認し、型定義を追加します:

json// tsconfig.json
{
  "compilerOptions": {
    "strict": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true
  }
}

型定義ファイルのインストール:

bashyarn add -D @types/react @types/node

エラー 3: 依存関係の循環参照

モジュール間で循環参照が発生している場合です。

bashCircular dependency detected:
src/components/Header.tsx -> src/components/Navigation.tsx -> src/components/Header.tsx

解決策

循環参照を解消するため、共通の型やユーティリティを別ファイルに分離します:

typescript// types/common.ts
export interface NavigationItem {
  label: string;
  href: string;
}

// components/Header.tsx
import { NavigationItem } from '../types/common';

// components/Navigation.tsx
import { NavigationItem } from '../types/common';

開発サーバーが起動しない場合

エラー 1: ポートが既に使用中

bashError: listen EADDRINUSE: address already in use :::3000

解決策

使用中のポートを確認し、プロセスを終了します:

bash# ポート3000を使用しているプロセスを確認
lsof -i :3000

# プロセスを終了
kill -9 <PID>

# または、別のポートで起動
yarn dev --port 3001

エラー 2: メモリ不足

bashFATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory

解決策

Node.js のメモリ制限を増やします:

bash# package.jsonのscriptsを修正
{
  "scripts": {
    "dev": "NODE_OPTIONS='--max-old-space-size=4096' next dev"
  }
}

エラー 3: 設定ファイルの構文エラー

bashSyntaxError: Unexpected token in JSON at position 123
Error: Invalid next.config.js

解決策

設定ファイルの構文を確認し、修正します:

javascript// next.config.js - 正しい例
/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    turbo: {
      rules: {
        '*.svg': {
          loaders: ['@svgr/webpack'],
          as: '*.js',
        },
      },
    },
  },
};

module.exports = nextConfig;

ホットリロードが動作しない場合

問題 1: ファイル監視が機能しない

ファイルを変更しても自動的にリロードされない場合です。

解決策

ファイル監視の設定を確認します:

javascript// next.config.js
const nextConfig = {
  webpack: (config, { dev, isServer }) => {
    if (dev && !isServer) {
      config.watchOptions = {
        poll: 1000,
        aggregateTimeout: 300,
      };
    }
    return config;
  },
};

問題 2: キャッシュの問題

古いキャッシュが原因でホットリロードが効かない場合です。

解決策

キャッシュをクリアして再起動します:

bash# キャッシュをクリア
rm -rf .next
rm -rf node_modules/.cache

# 依存関係を再インストール
yarn install

# 開発サーバーを再起動
yarn dev

依存関係の解決エラー

エラー 1: パッケージのバージョン競合

bashModule not found: Can't resolve 'react' in '/app/node_modules/next/dist/client'
Conflicting peer dependency "react@^18.0.0"

解決策

依存関係の競合を解決します:

bash# 依存関係の詳細を確認
yarn why react

# 競合するパッケージを更新
yarn upgrade react react-dom

# または、特定のバージョンを指定
yarn add react@^18.2.0 react-dom@^18.2.0

エラー 2: ピア依存関係の問題

bashwarning "next@13.4.0" has unmet peer dependency "react@^18.2.0"
warning "next@13.4.0" has unmet peer dependency "react-dom@^18.2.0"

解決策

ピア依存関係を正しくインストールします:

bash# ピア依存関係を確認
yarn list --pattern "react|react-dom"

# 不足している依存関係を追加
yarn add react@^18.2.0 react-dom@^18.2.0

メモリ不足エラー

エラー 1: ヒープメモリ不足

bashJavaScript heap out of memory
FATAL ERROR: Ineffective mark-compacts near heap limit

解決策

Node.js のメモリ制限を増やし、最適化を行います:

bash# package.jsonのscriptsを修正
{
  "scripts": {
    "dev": "NODE_OPTIONS='--max-old-space-size=8192' next dev",
    "build": "NODE_OPTIONS='--max-old-space-size=8192' next build"
  }
}

エラー 2: システムメモリ不足

bashError: spawn ENOMEM

解決策

システムリソースを確認し、不要なプロセスを終了します:

bash# メモリ使用量を確認
free -h

# 重いプロセスを確認
ps aux --sort=-%mem | head -10

# 不要なプロセスを終了
kill -9 <PID>

設定ファイルの問題

問題 1: next.config.js の設定ミス

bashError: Invalid next.config.js
TypeError: Cannot read property 'experimental' of undefined

解決策

設定ファイルの構文を修正します:

javascript// next.config.js - 正しい例
/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    turbo: {
      resolveAlias: {
        '@': './src',
      },
    },
  },
  webpack: (config) => {
    // カスタム設定
    return config;
  },
};

module.exports = nextConfig;

問題 2: TypeScript 設定の問題

bashType error: Cannot find type definition file for 'next'

解決策

TypeScript の設定を確認し、型定義を追加します:

json// tsconfig.json
{
  "compilerOptions": {
    "target": "es5",
    "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",
    "incremental": true,
    "plugins": [
      {
        "name": "next"
      }
    ],
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": [
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx",
    ".next/types/**/*.ts"
  ],
  "exclude": ["node_modules"]
}

デバッグ方法

ログの確認方法

Turbopack の詳細なログを確認することで、問題の原因を特定できます。

デバッグログの有効化

bash# 環境変数でデバッグログを有効化
DEBUG=* yarn dev

# または、Next.jsのデバッグログ
NODE_OPTIONS='--inspect' yarn dev

ログレベルの設定

javascript// next.config.js
const nextConfig = {
  logging: {
    fetches: {
      fullUrl: true,
    },
  },
};

デバッグモードの有効化

開発者ツールでのデバッグ

javascript// ブラウザのコンソールで実行
console.log('Turbopack debug info:', window.__NEXT_DATA__);

Node.js デバッガーの使用

bash# デバッガーを有効にして起動
NODE_OPTIONS='--inspect-brk' yarn dev

パフォーマンス分析

ビルド時間の測定

bash# ビルド時間を測定
time yarn build

# 詳細なビルド情報を表示
yarn build --debug

メモリ使用量の監視

bash# メモリ使用量を監視
node --max-old-space-size=4096 -e "
const used = process.memoryUsage();
console.log('Memory usage:');
console.log('RSS:', Math.round(used.rss / 1024 / 1024), 'MB');
console.log('Heap Total:', Math.round(used.heapTotal / 1024 / 1024), 'MB');
console.log('Heap Used:', Math.round(used.heapUsed / 1024 / 1024), 'MB');
"

予防策とベストプラクティス

プロジェクト構造の最適化

効率的なプロジェクト構造を維持することで、多くの問題を予防できます。

推奨ディレクトリ構造

bashsrc/
├── components/     # 再利用可能なコンポーネント
├── pages/         # ページコンポーネント
├── hooks/         # カスタムフック
├── utils/         # ユーティリティ関数
├── types/         # TypeScript型定義
├── styles/        # スタイルファイル
└── constants/     # 定数定義

インポートパスの統一

typescript// tsconfig.jsonでパスエイリアスを設定
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
      "@/components/*": ["./src/components/*"],
      "@/utils/*": ["./src/utils/*"]
    }
  }
}

依存関係の管理

定期的な更新

bash# 依存関係の更新確認
yarn outdated

# セキュリティ脆弱性の確認
yarn audit

# 依存関係の更新
yarn upgrade-interactive --latest

バージョン固定

json// package.json
{
  "dependencies": {
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "next": "13.4.0"
  },
  "resolutions": {
    "react": "18.2.0",
    "react-dom": "18.2.0"
  }
}

開発環境の最適化

キャッシュの活用

javascript// next.config.js
const nextConfig = {
  experimental: {
    turbo: {
      rules: {
        '*.svg': {
          loaders: ['@svgr/webpack'],
          as: '*.js',
        },
      },
    },
  },
  // キャッシュの設定
  onDemandEntries: {
    maxInactiveAge: 25 * 1000,
    pagesBufferLength: 2,
  },
};

ファイル監視の最適化

javascript// next.config.js
const nextConfig = {
  webpack: (config, { dev, isServer }) => {
    if (dev && !isServer) {
      config.watchOptions = {
        poll: 1000,
        aggregateTimeout: 300,
        ignored: ['**/node_modules', '**/.git'],
      };
    }
    return config;
  },
};

エラーハンドリングの実装

グローバルエラーハンドラー

typescript// pages/_error.tsx
import { NextPageContext } from 'next';

interface ErrorProps {
  statusCode?: number;
}

function Error({ statusCode }: ErrorProps) {
  return (
    <p>
      {statusCode
        ? `An error ${statusCode} occurred on server`
        : 'An error occurred on client'}
    </p>
  );
}

Error.getInitialProps = ({ res, err }: NextPageContext) => {
  const statusCode = res
    ? res.statusCode
    : err
    ? err.statusCode
    : 404;
  return { statusCode };
};

export default Error;

開発時のエラー表示

typescript// components/ErrorBoundary.tsx
import React, {
  Component,
  ErrorInfo,
  ReactNode,
} from 'react';

interface Props {
  children: ReactNode;
}

interface State {
  hasError: boolean;
  error?: Error;
}

class ErrorBoundary extends Component<Props, State> {
  public state: State = {
    hasError: false,
  };

  public static getDerivedStateFromError(
    error: Error
  ): State {
    return { hasError: true, error };
  }

  public componentDidCatch(
    error: Error,
    errorInfo: ErrorInfo
  ) {
    console.error('Uncaught error:', error, errorInfo);
  }

  public render() {
    if (this.state.hasError) {
      return (
        <div>
          <h1>エラーが発生しました</h1>
          <p>{this.state.error?.message}</p>
        </div>
      );
    }

    return this.props.children;
  }
}

export default ErrorBoundary;

まとめ

Turbopack のトラブルシューティングは、最初は複雑に感じるかもしれません。しかし、問題のパターンを理解し、適切な解決策を身につけることで、開発効率を大きく向上させることができます。

重要なポイントをまとめると:

  1. エラーメッセージを正確に読み取る: エラーの詳細を理解することで、適切な解決策を見つけられます

  2. 段階的に問題を切り分ける: 大きな問題を小さな部分に分けて、一つずつ解決していくことが大切です

  3. 予防的な対策を講じる: 定期的な依存関係の更新や、適切なプロジェクト構造の維持が重要です

  4. デバッグツールを活用する: ログやデバッガーを効果的に使うことで、問題の原因を素早く特定できます

Turbopack は急速に発展しているツールです。新しい機能や改善が次々と追加されているため、公式ドキュメントやコミュニティの情報を定期的にチェックすることをお勧めします。

問題に遭遇した際は、焦らずに一つずつ対処していくことで、必ず解決策を見つけることができます。この記事が、あなたの Turbopack 開発をより快適にする一助となれば幸いです。

関連リンク