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

開発の現場で Turbopack を使い始めたものの、思わぬエラーに遭遇して困った経験はありませんか?
「ビルドが通らない」「開発サーバーが起動しない」「ホットリロードが効かない」など、Turbopack 特有の問題に直面すると、開発効率が大きく下がってしまいます。
この記事では、Turbopack でよく発生する問題とその解決策を、実際のエラーコードとともに詳しく解説します。問題解決のコツを身につけて、スムーズな開発環境を構築しましょう。
Turbopack とは
Turbopack は、Vercel が開発した次世代の JavaScript バンドラーです。Rust で書かれており、Webpack の後継として設計されています。
Turbopack の特徴
- 高速なビルド: インクリメンタルコンパイルにより、変更箇所のみを再ビルド
- メモリ効率: より少ないメモリ使用量で大規模プロジェクトを処理
- 開発サーバー: 高速なホットリロード機能
- Next.js 統合: Next.js 13 以降でデフォルトのバンドラーとして採用
従来の Webpack との違い
項目 | Webpack | Turbopack |
---|---|---|
言語 | JavaScript | Rust |
ビルド速度 | 標準 | 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 のトラブルシューティングは、最初は複雑に感じるかもしれません。しかし、問題のパターンを理解し、適切な解決策を身につけることで、開発効率を大きく向上させることができます。
重要なポイントをまとめると:
-
エラーメッセージを正確に読み取る: エラーの詳細を理解することで、適切な解決策を見つけられます
-
段階的に問題を切り分ける: 大きな問題を小さな部分に分けて、一つずつ解決していくことが大切です
-
予防的な対策を講じる: 定期的な依存関係の更新や、適切なプロジェクト構造の維持が重要です
-
デバッグツールを活用する: ログやデバッガーを効果的に使うことで、問題の原因を素早く特定できます
Turbopack は急速に発展しているツールです。新しい機能や改善が次々と追加されているため、公式ドキュメントやコミュニティの情報を定期的にチェックすることをお勧めします。
問題に遭遇した際は、焦らずに一つずつ対処していくことで、必ず解決策を見つけることができます。この記事が、あなたの Turbopack 開発をより快適にする一助となれば幸いです。
関連リンク
- review
今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
- review
ついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
- review
愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
- review
週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
- review
新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
- review
科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来