Turbopack 迁移指南 #

迁移概述 #

迁移前准备 #

在开始迁移之前,请确保:

text
✅ Node.js >= 18.17.0
✅ Next.js >= 13.0.0(如果使用 Next.js)
✅ 了解项目当前的构建配置
✅ 有完整的测试覆盖
✅ 有回滚计划

迁移流程 #

text
┌─────────────────────────────────────────────────────────────┐
│                    迁移流程                                  │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│   1. 评估项目                                                │
│      └── 检查依赖、配置、插件                                │
│                                                              │
│   2. 备份项目                                                │
│      └── Git 分支、配置文件备份                              │
│                                                              │
│   3. 安装 Turbopack                                          │
│      └── 更新依赖、配置                                      │
│                                                              │
│   4. 转换配置                                                │
│      └── 将 Webpack/Vite 配置转换为 Turbopack               │
│                                                              │
│   5. 测试验证                                                │
│      └── 开发模式、生产构建、功能测试                        │
│                                                              │
│   6. 修复问题                                                │
│      └── 解决兼容性问题                                      │
│                                                              │
│   7. 部署上线                                                │
│      └── 更新 CI/CD 配置                                     │
│                                                              │
└─────────────────────────────────────────────────────────────┘

从 Webpack 迁移 #

配置对比 #

入口配置 #

javascript
// webpack.config.js
module.exports = {
  entry: './src/index.js',
};

// next.config.js (Turbopack)
module.exports = {
  experimental: {
    turbo: {},
  },
};

输出配置 #

javascript
// webpack.config.js
module.exports = {
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[contenthash].js',
    publicPath: '/assets/',
  },
};

// Turbopack 通过 Next.js 自动处理输出
// 无需手动配置

模块解析 #

javascript
// webpack.config.js
module.exports = {
  resolve: {
    extensions: ['.tsx', '.ts', '.js', '.json'],
    alias: {
      '@': path.resolve(__dirname, 'src'),
      '@components': path.resolve(__dirname, 'src/components'),
    },
  },
};

// next.config.js (Turbopack)
module.exports = {
  experimental: {
    turbo: {
      resolveExtensions: ['.tsx', '.ts', '.js', '.json'],
      resolveAlias: {
        '@': './src',
        '@components': './src/components',
      },
    },
  },
};

Loader 转换 #

javascript
// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
      },
      {
        test: /\.scss$/,
        use: ['style-loader', 'css-loader', 'sass-loader'],
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        type: 'asset/resource',
      },
    ],
  },
};

// next.config.js (Turbopack)
module.exports = {
  experimental: {
    turbo: {
      rules: {
        '*.scss': {
          loaders: ['sass-loader'],
        },
      },
    },
  },
};

插件转换 #

javascript
// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
    }),
    new MiniCssExtractPlugin(),
  ],
};

// Turbopack 不需要这些插件
// Next.js 自动处理 HTML 和 CSS

完整迁移示例 #

迁移前(Webpack) #

javascript
// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[contenthash].js',
    clean: true,
  },
  resolve: {
    extensions: ['.tsx', '.ts', '.js', '.jsx', '.json'],
    alias: {
      '@': path.resolve(__dirname, 'src'),
      '@components': path.resolve(__dirname, 'src/components'),
      '@utils': path.resolve(__dirname, 'src/utils'),
    },
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      },
      {
        test: /\.scss$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        type: 'asset/resource',
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
    }),
    new MiniCssExtractPlugin({
      filename: '[name].[contenthash].css',
    }),
  ],
  devServer: {
    static: './dist',
    hot: true,
    port: 3000,
  },
};

迁移后(Turbopack + Next.js) #

javascript
// next.config.js
module.exports = {
  experimental: {
    turbo: {
      resolveExtensions: ['.tsx', '.ts', '.js', '.jsx', '.json'],
      resolveAlias: {
        '@': './src',
        '@components': './src/components',
        '@utils': './src/utils',
      },
      rules: {
        '*.scss': {
          loaders: ['sass-loader'],
        },
      },
    },
  },
};
json
// package.json
{
  "scripts": {
    "dev": "next dev --turbo",
    "build": "next build",
    "start": "next start"
  }
}

Webpack 插件兼容性 #

插件 兼容性 替代方案
html-webpack-plugin ✅ 不需要 Next.js 内置
mini-css-extract-plugin ✅ 不需要 Next.js 内置
copy-webpack-plugin ⚠️ 部分 public 目录
define-plugin ✅ 支持 env 配置
provide-plugin ⚠️ 部分 全局导入
compression-webpack-plugin ✅ 不需要 服务器配置
bundle-analyzer ⚠️ 有限 –analyze 选项

从 Vite 迁移 #

配置对比 #

基本配置 #

javascript
// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },
  server: {
    port: 3000,
  },
});

// next.config.js (Turbopack)
module.exports = {
  experimental: {
    turbo: {
      resolveAlias: {
        '@': './src',
      },
    },
  },
};

CSS 配置 #

javascript
// vite.config.js
export default defineConfig({
  css: {
    modules: {
      localsConvention: 'camelCase',
    },
    preprocessorOptions: {
      scss: {
        additionalData: `@import "@/styles/variables.scss";`,
      },
    },
  },
});

// next.config.js (Turbopack)
module.exports = {
  experimental: {
    turbo: {
      rules: {
        '*.scss': {
          loaders: [
            {
              loader: 'sass-loader',
              options: {
                additionalData: `@import "@/styles/variables.scss";`,
              },
            },
          ],
        },
      },
    },
  },
};

环境变量 #

javascript
// vite.config.js
export default defineConfig({
  define: {
    __APP_VERSION__: JSON.stringify('1.0.0'),
  },
});

// next.config.js (Turbopack)
module.exports = {
  env: {
    NEXT_PUBLIC_APP_VERSION: '1.0.0',
  },
};

完整迁移示例 #

迁移前(Vite) #

javascript
// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import svgr from 'vite-plugin-svgr';
import path from 'path';

export default defineConfig({
  plugins: [react(), svgr()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
      '@components': path.resolve(__dirname, './src/components'),
    },
  },
  css: {
    modules: {
      localsConvention: 'camelCase',
    },
  },
  server: {
    port: 3000,
    proxy: {
      '/api': {
        target: 'http://localhost:8080',
        changeOrigin: true,
      },
    },
  },
  build: {
    outDir: 'dist',
    sourcemap: true,
  },
});

迁移后(Turbopack + Next.js) #

javascript
// next.config.js
module.exports = {
  experimental: {
    turbo: {
      resolveAlias: {
        '@': './src',
        '@components': './src/components',
      },
      rules: {
        '*.svg': {
          loaders: ['@svgr/webpack'],
          as: '*.js',
        },
      },
    },
  },
  async rewrites() {
    return [
      {
        source: '/api/:path*',
        destination: 'http://localhost:8080/api/:path*',
      },
    ];
  },
};

Vite 特性兼容性 #

特性 兼容性 说明
CSS Modules ✅ 支持 自动处理
CSS 预处理器 ✅ 支持 需配置 rules
环境变量 ✅ 支持 使用 NEXT_PUBLIC_ 前缀
代理 ✅ 支持 使用 rewrites
SVG 组件 ✅ 支持 配置 rules
动态导入 ✅ 支持 原生支持
Glob 导入 ⚠️ 部分 使用 require.context

从 Next.js Webpack 迁移 #

启用 Turbopack #

json
// package.json
{
  "scripts": {
    "dev": "next dev --turbo",
    "build": "next build"
  }
}

配置迁移 #

javascript
// next.config.js (Webpack)
module.exports = {
  webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
    config.resolve.alias['@'] = path.join(__dirname, 'src');
    config.module.rules.push({
      test: /\.svg$/,
      use: ['@svgr/webpack'],
    });
    return config;
  },
};

// next.config.js (Turbopack)
module.exports = {
  experimental: {
    turbo: {
      resolveAlias: {
        '@': './src',
      },
      rules: {
        '*.svg': {
          loaders: ['@svgr/webpack'],
          as: '*.js',
        },
      },
    },
  },
};

Webpack 配置兼容 #

javascript
// next.config.js
module.exports = {
  webpack: (config) => {
    // Webpack 特定配置
    // 仅在生产构建时使用
    return config;
  },
  
  experimental: {
    turbo: {
      // Turbopack 配置
      // 开发模式使用
    },
  },
};

常见迁移问题 #

问题一:模块解析失败 #

bash
# 错误
Error: Cannot find module '@/components/Button'

解决方案

javascript
// next.config.js
module.exports = {
  experimental: {
    turbo: {
      resolveAlias: {
        '@': './src',
        '@/components': './src/components',
      },
    },
  },
};

问题二:CSS 导入失败 #

bash
# 错误
Error: Cannot find module './styles.module.css'

解决方案

javascript
// 确保文件扩展名正确
import styles from './styles.module.css'; // ✅
import styles from './styles.css';        // ❌ 如果文件是 .module.css

问题三:SVG 导入失败 #

bash
# 错误
Error: Cannot find module './logo.svg'

解决方案

javascript
// next.config.js
module.exports = {
  experimental: {
    turbo: {
      rules: {
        '*.svg': {
          loaders: ['@svgr/webpack'],
          as: '*.js',
        },
      },
    },
  },
};
tsx
// 使用方式
import Logo from './logo.svg';

export function Header() {
  return <Logo className="w-10 h-10" />;
}

问题四:环境变量未生效 #

bash
# 错误
ReferenceError: process.env.API_URL is not defined

解决方案

bash
# .env.local
NEXT_PUBLIC_API_URL=https://api.example.com
tsx
// 使用
const apiUrl = process.env.NEXT_PUBLIC_API_URL;

问题五:第三方库兼容问题 #

bash
# 错误
Error: Cannot find module 'some-library'

解决方案

javascript
// next.config.js
module.exports = {
  experimental: {
    turbo: {
      resolveAlias: {
        'some-library': 'some-library/dist/esm/index.js',
      },
    },
  },
};

迁移检查清单 #

迁移前检查 #

text
□ 确认 Node.js 版本 >= 18.17.0
□ 确认 Next.js 版本 >= 13.0.0
□ 备份当前配置文件
□ 创建新分支
□ 记录当前构建时间(用于对比)

配置迁移检查 #

text
□ 入口配置
□ 输出配置
□ 模块解析配置
□ Loader 配置
□ 插件配置
□ 环境变量配置
□ 开发服务器配置
□ 生产构建配置

功能测试检查 #

text
□ 开发服务器启动
□ 热更新功能
□ 页面路由
□ API 路由
□ CSS 样式
□ 图片资源
□ 字体资源
□ 环境变量
□ 第三方库
□ TypeScript 编译
□ ESLint 检查

性能对比检查 #

text
□ 冷启动时间
□ HMR 时间
□ 生产构建时间
□ 构建产物大小
□ 页面加载时间

迁移策略 #

渐进式迁移 #

text
阶段一:开发环境迁移
├── 启用 Turbopack 开发模式
├── 测试开发体验
└── 修复兼容性问题

阶段二:生产构建测试
├── 测试生产构建
├── 对比构建产物
└── 性能基准测试

阶段三:全面迁移
├── 更新 CI/CD 配置
├── 更新团队文档
└── 移除旧配置

回滚计划 #

bash
# 保留原配置文件
cp webpack.config.js webpack.config.js.backup
cp vite.config.js vite.config.js.backup

# 回滚脚本
# package.json
{
  "scripts": {
    "dev:webpack": "webpack serve",
    "dev:turbo": "next dev --turbo",
    "dev": "npm run dev:turbo"
  }
}

CI/CD 配置更新 #

GitHub Actions #

yaml
# .github/workflows/ci.yml
name: CI

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: Build
        run: npm run build
      
      - name: Test
        run: npm test

缓存配置 #

yaml
# .github/workflows/ci.yml
- name: Cache Turbopack
  uses: actions/cache@v4
  with:
    path: |
      .turbo
      .next/cache
    key: ${{ runner.os }}-turbo-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-turbo-

迁移后优化 #

性能优化 #

javascript
// turbo.json
{
  "pipeline": {
    "build": {
      "outputs": [".next/**", "!.next/cache/**"],
      "dependsOn": ["^build"]
    }
  }
}

缓存优化 #

bash
# 配置远程缓存
turbo login
turbo link

# 团队共享缓存
turbo config set team my-team

监控配置 #

javascript
// next.config.js
module.exports = {
  experimental: {
    turbo: {
      profiling: true,
    },
  },
};

下一步 #

现在你已经了解了如何迁移到 Turbopack,接下来学习 高级用法 探索更多高级功能!

最后更新:2026-03-28