Turbopack 基础使用 #
安装 Turbopack #
系统要求 #
text
Node.js: >= 18.17.0
操作系统: macOS, Linux, Windows
内存: >= 4GB (推荐 8GB+)
方式一:Next.js 项目 #
Next.js 13+ 内置 Turbopack 支持:
bash
# 创建新项目
npx create-next-app@latest my-app
# 进入项目目录
cd my-app
# 使用 Turbopack 启动开发服务器
npm run dev -- --turbo
方式二:独立安装 #
bash
# 全局安装
npm install -g turbo
# 或作为项目依赖
npm install --save-dev turbo
命令行使用 #
基本命令 #
bash
# 开发模式
turbo dev
# 构建生产版本
turbo build
# 监听模式
turbo watch
命令行选项 #
| 选项 | 描述 | 示例 |
|---|---|---|
--port |
指定端口 | turbo dev --port 3001 |
--host |
指定主机 | turbo dev --host 0.0.0.0 |
--config |
指定配置文件 | turbo dev --config turbo.json |
--cache-dir |
缓存目录 | turbo dev --cache-dir .turbo |
--no-cache |
禁用缓存 | turbo build --no-cache |
--profile |
性能分析 | turbo build --profile |
开发服务器 #
bash
# 启动开发服务器
turbo dev
# 指定端口
turbo dev --port 3001
# 允许外部访问
turbo dev --host 0.0.0.0
# 禁用自动打开浏览器
turbo dev --no-open
生产构建 #
bash
# 构建
turbo build
# 分析构建结果
turbo build --analyze
# 生成性能报告
turbo build --profile
Next.js 集成 #
启用 Turbopack #
json
// package.json
{
"scripts": {
"dev": "next dev --turbo",
"build": "next build",
"start": "next start"
}
}
配置文件 #
javascript
// next.config.js
module.exports = {
experimental: {
turbo: {
resolveExtensions: ['.tsx', '.ts', '.jsx', '.js', '.json'],
resolveAlias: {
'@': './src',
'@components': './src/components',
},
},
},
}
开发体验 #
bash
# 启动开发服务器
npm run dev
# 输出示例
# ▲ Next.js 14.0.0
# - Local: http://localhost:3000
# - Turbopack: enabled
#
# ✓ Ready in 0.5s
项目结构 #
基本结构 #
text
my-project/
├── src/
│ ├── app/
│ │ ├── layout.tsx
│ │ ├── page.tsx
│ │ └── globals.css
│ ├── components/
│ │ ├── Header.tsx
│ │ └── Footer.tsx
│ └── lib/
│ └── utils.ts
├── public/
│ └── images/
├── next.config.js
├── turbo.json
└── package.json
Turbopack 配置文件 #
json
// turbo.json
{
"$schema": "https://turbo.build/schema.json",
"pipeline": {
"build": {
"outputs": [".next/**", "!.next/cache/**"]
},
"dev": {
"cache": false,
"persistent": true
}
}
}
模块解析 #
路径别名 #
javascript
// next.config.js
module.exports = {
experimental: {
turbo: {
resolveAlias: {
'@': './src',
'@components': './src/components',
'@lib': './src/lib',
'@styles': './src/styles',
'@hooks': './src/hooks',
'@utils': './src/utils',
},
},
},
}
tsx
// 使用别名导入
import Header from '@/components/Header';
import { formatDate } from '@utils/date';
import styles from '@styles/Button.module.css';
扩展名解析 #
javascript
// next.config.js
module.exports = {
experimental: {
turbo: {
resolveExtensions: [
'.tsx',
'.ts',
'.jsx',
'.js',
'.json',
'.css',
'.scss',
],
},
},
}
tsx
// 导入时可以省略扩展名
import Header from './Header'; // 解析为 Header.tsx
import styles from './Button.css'; // 解析为 Button.css
TypeScript 支持 #
原生支持 #
Turbopack 原生支持 TypeScript,无需额外配置:
tsx
// src/app/page.tsx
interface User {
id: number;
name: string;
email: string;
}
async function fetchUser(id: number): Promise<User> {
const res = await fetch(`/api/users/${id}`);
return res.json();
}
export default async function Page() {
const user = await fetchUser(1);
return <div>Hello, {user.name}</div>;
}
类型检查 #
bash
# 单独运行类型检查
npx tsc --noEmit
# 或在 package.json 中添加脚本
{
"scripts": {
"type-check": "tsc --noEmit"
}
}
tsconfig.json #
json
{
"compilerOptions": {
"target": "ES2020",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"moduleResolution": "bundler",
"jsx": "preserve",
"strict": true,
"paths": {
"@/*": ["./src/*"],
"@components/*": ["./src/components/*"]
}
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
CSS 处理 #
CSS Modules #
css
/* Button.module.css */
.button {
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
}
.primary {
background-color: #0070f3;
color: white;
}
.secondary {
background-color: #6c757d;
color: white;
}
tsx
// Button.tsx
import styles from './Button.module.css';
interface ButtonProps {
variant?: 'primary' | 'secondary';
children: React.ReactNode;
}
export function Button({ variant = 'primary', children }: ButtonProps) {
return (
<button className={`${styles.button} ${styles[variant]}`}>
{children}
</button>
);
}
全局样式 #
css
/* globals.css */
:root {
--primary-color: #0070f3;
--text-color: #333;
--background: #fff;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
color: var(--text-color);
background: var(--background);
}
tsx
// layout.tsx
import './globals.css';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="zh">
<body>{children}</body>
</html>
);
}
CSS 预处理器 #
javascript
// next.config.js
module.exports = {
experimental: {
turbo: {
rules: {
'*.scss': {
loaders: ['sass-loader'],
},
'*.less': {
loaders: ['less-loader'],
},
},
},
},
}
scss
// styles.module.scss
$primary: #0070f3;
.button {
background: $primary;
&:hover {
background: darken($primary, 10%);
}
}
静态资源 #
图片处理 #
tsx
// 使用 Next.js Image 组件
import Image from 'next/image';
export function Logo() {
return (
<Image
src="/images/logo.png"
alt="Logo"
width={200}
height={100}
priority
/>
);
}
静态文件 #
text
public/
├── images/
│ ├── logo.png
│ └── hero.jpg
├── fonts/
│ └── custom.woff2
└── favicon.ico
tsx
// 引用静态资源
<img src="/images/logo.png" alt="Logo" />
// 字体
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom.woff2') format('woff2');
}
热模块替换(HMR) #
自动 HMR #
Turbopack 自动处理 HMR:
tsx
// Counter.tsx
import { useState } from 'react';
export function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(c => c + 1)}>
Increment
</button>
</div>
);
}
修改代码后,组件会自动更新,状态保持不变。
HMR 性能 #
text
┌─────────────────────────────────────────────────────────────┐
│ HMR 时间对比 │
├─────────────────────────────────────────────────────────────┤
│ │
│ Webpack: ████████████████████████████ 3000ms │
│ │
│ Vite: ████████ 200ms │
│ │
│ Turbopack: █ 10ms │
│ │
└─────────────────────────────────────────────────────────────┘
Fast Refresh #
React Fast Refresh 自动保留组件状态:
tsx
// 修改前
export function Greeting({ name }: { name: string }) {
return <h1>Hello, {name}!</h1>;
}
// 修改后 - 状态保持
export function Greeting({ name }: { name: string }) {
return <h1>Welcome, {name}!</h1>;
}
环境变量 #
定义环境变量 #
bash
# .env.local
DATABASE_URL=postgresql://localhost:5432/mydb
API_KEY=your-api-key
NEXT_PUBLIC_API_URL=https://api.example.com
使用环境变量 #
tsx
// 服务端
async function connectDB() {
const url = process.env.DATABASE_URL;
// 连接数据库
}
// 客户端(需要 NEXT_PUBLIC_ 前缀)
const apiUrl = process.env.NEXT_PUBLIC_API_URL;
export function DataFetcher() {
const [data, setData] = useState(null);
useEffect(() => {
fetch(apiUrl).then(res => res.json()).then(setData);
}, []);
return <pre>{JSON.stringify(data, null, 2)}</pre>;
}
环境变量类型 #
typescript
// env.d.ts
namespace NodeJS {
interface ProcessEnv {
DATABASE_URL: string;
API_KEY: string;
NEXT_PUBLIC_API_URL: string;
NODE_ENV: 'development' | 'production' | 'test';
}
}
开发工具 #
浏览器 DevTools #
Turbopack 提供开发工具集成:
tsx
// React DevTools 可以正常使用
// 组件树、Props、State 都可以查看
调试配置 #
json
// .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Next.js: debug full stack",
"type": "node-terminal",
"request": "launch",
"command": "npm run dev"
}
]
}
日志输出 #
bash
# 开发模式日志
turbo dev --log-level verbose
# 输出示例
# [turbopack] Compiling...
# [turbopack] Compiled successfully in 50ms
# [turbopack] HMR update: /src/app/page.tsx
常见问题排查 #
问题一:端口被占用 #
bash
# 错误
Error: Port 3000 is already in use
# 解决方案
turbo dev --port 3001
问题二:缓存问题 #
bash
# 清除缓存
rm -rf .turbo
rm -rf .next
# 重新启动
turbo dev
问题三:模块找不到 #
bash
# 错误
Module not found: Can't resolve '@/components/Header'
# 解决方案:检查路径别名配置
// next.config.js
module.exports = {
experimental: {
turbo: {
resolveAlias: {
'@': './src',
},
},
},
}
问题四:类型错误 #
bash
# 运行类型检查
npx tsc --noEmit
# 常见原因
# 1. tsconfig.json 配置错误
# 2. 缺少类型定义
# 3. 路径别名未同步
性能优化 #
缓存策略 #
json
// turbo.json
{
"pipeline": {
"build": {
"outputs": [".next/**", "!.next/cache/**"],
"dependsOn": ["^build"]
}
}
}
按需编译 #
Turbopack 自动按需编译:
text
┌─────────────────────────────────────────────────────────────┐
│ 按需编译 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 访问 /page-a ──► 只编译 page-a 相关模块 │
│ │
│ 访问 /page-b ──► 只编译 page-b 相关模块 │
│ │
│ 其他页面 ──► 不编译 │
│ │
└─────────────────────────────────────────────────────────────┘
减少依赖 #
javascript
// 避免导入整个库
import _ from 'lodash'; // ❌ 导入整个库
// 只导入需要的函数
import debounce from 'lodash/debounce'; // ✅ 只导入需要的
实战示例 #
示例一:创建组件 #
tsx
// src/components/Card.tsx
interface CardProps {
title: string;
description: string;
image?: string;
}
export function Card({ title, description, image }: CardProps) {
return (
<div className="card">
{image && <img src={image} alt={title} />}
<h3>{title}</h3>
<p>{description}</p>
</div>
);
}
css
/* Card.module.css */
.card {
border: 1px solid #e0e0e0;
border-radius: 8px;
padding: 16px;
transition: box-shadow 0.2s;
}
.card:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.card img {
width: 100%;
height: 200px;
object-fit: cover;
border-radius: 4px;
}
.card h3 {
margin: 12px 0 8px;
font-size: 18px;
}
.card p {
color: #666;
font-size: 14px;
}
示例二:API 路由 #
typescript
// src/app/api/users/route.ts
import { NextResponse } from 'next/server';
interface User {
id: number;
name: string;
email: string;
}
const users: User[] = [
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' },
];
export async function GET() {
return NextResponse.json(users);
}
export async function POST(request: Request) {
const body = await request.json();
const newUser: User = {
id: users.length + 1,
...body,
};
users.push(newUser);
return NextResponse.json(newUser, { status: 201 });
}
示例三:数据获取 #
tsx
// src/app/users/page.tsx
interface User {
id: number;
name: string;
email: string;
}
async function getUsers(): Promise<User[]> {
const res = await fetch('/api/users', {
cache: 'no-store',
});
return res.json();
}
export default async function UsersPage() {
const users = await getUsers();
return (
<div>
<h1>Users</h1>
<ul>
{users.map(user => (
<li key={user.id}>
{user.name} - {user.email}
</li>
))}
</ul>
</div>
);
}
下一步 #
现在你已经掌握了 Turbopack 的基础使用方法,接下来学习 配置详解 深入了解各种配置选项!
最后更新:2026-03-28