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