Turbopack 高级用法 #
Monorepo 支持 #
什么是 Monorepo? #
Monorepo 是一种将多个项目放在同一个仓库中管理的开发策略:
text
┌─────────────────────────────────────────────────────────────┐
│ Monorepo 结构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ my-monorepo/ │
│ ├── apps/ │
│ │ ├── web/ # Web 应用 │
│ │ ├── admin/ # 管理后台 │
│ │ └── docs/ # 文档站点 │
│ ├── packages/ │
│ │ ├── ui/ # UI 组件库 │
│ │ ├── utils/ # 工具函数库 │
│ │ └── config/ # 共享配置 │
│ ├── turbo.json # Turbopack 配置 │
│ └── package.json # 根 package.json │
│ │
└─────────────────────────────────────────────────────────────┘
配置 Monorepo #
根目录配置 #
json
// package.json
{
"name": "my-monorepo",
"private": true,
"workspaces": [
"apps/*",
"packages/*"
],
"devDependencies": {
"turbo": "^2.0.0"
},
"scripts": {
"dev": "turbo dev",
"build": "turbo build",
"test": "turbo test",
"lint": "turbo lint"
}
}
Turbopack 配置 #
json
// turbo.json
{
"$schema": "https://turbo.build/schema.json",
"globalDependencies": ["**/.env.*local"],
"globalEnv": ["NODE_ENV"],
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**", "dist/**"]
},
"dev": {
"cache": false,
"persistent": true
},
"lint": {
"outputs": []
},
"test": {
"dependsOn": ["build"],
"outputs": ["coverage/**"]
},
"clean": {
"cache": false
}
}
}
应用配置 #
json
// apps/web/package.json
{
"name": "@my-org/web",
"version": "1.0.0",
"dependencies": {
"@my-org/ui": "*",
"@my-org/utils": "*",
"next": "^14.0.0",
"react": "^18.2.0"
},
"scripts": {
"dev": "next dev --turbo",
"build": "next build",
"start": "next start"
}
}
包配置 #
json
// packages/ui/package.json
{
"name": "@my-org/ui",
"version": "1.0.0",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"./styles.css": "./dist/styles.css"
},
"scripts": {
"build": "tsup src/index.ts --format esm,cjs --dts",
"dev": "tsup src/index.ts --format esm,cjs --watch"
},
"peerDependencies": {
"react": "^18.0.0"
}
}
任务编排 #
json
// turbo.json
{
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**"]
},
"test": {
"dependsOn": ["build"],
"outputs": ["coverage/**"],
"inputs": ["src/**/*", "test/**/*"]
},
"lint": {
"dependsOn": ["^build"],
"outputs": []
},
"type-check": {
"dependsOn": ["^build"],
"outputs": []
}
}
}
并行执行 #
bash
# 并行构建所有包
turbo build --parallel
# 并行测试
turbo test --parallel
# 过滤特定包
turbo build --filter=@my-org/web
turbo build --filter='./apps/*'
增量构建 #
bash
# 只构建变化的包
turbo build --filter=...[origin/main]
# 只构建依赖变化的包
turbo build --filter=...{HEAD}
远程缓存 #
配置远程缓存 #
bash
# 登录 Vercel
turbo login
# 关联项目
turbo link
# 配置团队
turbo config set team my-team
远程缓存配置 #
json
// turbo.json
{
"remoteCache": {
"enabled": true,
"signature": true
}
}
CI/CD 集成 #
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: Cache Turbopack
uses: actions/cache@v4
with:
path: .turbo
key: ${{ runner.os }}-turbo-${{ hashFiles('**/package-lock.json') }}
- name: Build
run: npm run build
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
自定义远程缓存 #
javascript
// custom-cache-server.js
const express = require('express');
const { createClient } = require('@vercel/blob');
const app = express();
const blob = createClient({
token: process.env.BLOB_READ_WRITE_TOKEN,
});
app.put('/v8/artifacts/:hash', async (req, res) => {
const { hash } = req.params;
await blob.put(`artifacts/${hash}`, req);
res.json({ status: 'ok' });
});
app.get('/v8/artifacts/:hash', async (req, res) => {
const { hash } = req.params;
const blob = await blob.get(`artifacts/${hash}`);
if (!blob) {
return res.status(404).json({ error: 'Not found' });
}
blob.pipe(res);
});
app.listen(3001);
bash
# 配置自定义缓存服务器
turbo config set api-url http://localhost:3001
自定义插件 #
插件架构 #
text
┌─────────────────────────────────────────────────────────────┐
│ 插件系统 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Plugin Interface │ │
│ │ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ │
│ │ │ name │ │ version │ │ hooks │ │ │
│ │ └───────────┘ └───────────┘ └───────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Plugin Hooks │ │
│ │ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ │
│ │ │ onInit │ │ onBuild │ │ onEmit │ │ │
│ │ └───────────┘ └───────────┘ └───────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
创建插件 #
javascript
// plugins/my-plugin.js
module.exports = function myPlugin(options = {}) {
return {
name: 'my-plugin',
setup(build) {
build.onResolve({ filter: /^my-lib:/ }, async (args) => {
const path = args.path.replace('my-lib:', '');
return { path: `./lib/${path}.js` };
});
build.onLoad({ filter: /\.custom$/ }, async (args) => {
const content = await fs.readFile(args.path, 'utf8');
return {
contents: transformCustom(content),
loader: 'js',
};
});
},
};
};
使用插件 #
javascript
// next.config.js
module.exports = {
experimental: {
turbo: {
plugins: [
require('./plugins/my-plugin')({
option1: 'value1',
}),
],
},
},
};
插件钩子 #
javascript
module.exports = function myPlugin() {
return {
name: 'my-plugin',
setup(build) {
build.onStart(() => {
console.log('Build started');
});
build.onEnd((result) => {
console.log('Build finished');
console.log('Warnings:', result.warnings);
console.log('Errors:', result.errors);
});
build.onResolve({ filter: /.*/ }, async (args) => {
if (args.path.startsWith('@')) {
return { path: args.path, external: true };
}
return null;
});
build.onLoad({ filter: /\.txt$/ }, async (args) => {
const content = await fs.readFile(args.path, 'utf8');
return {
contents: `export default ${JSON.stringify(content)}`,
loader: 'js',
};
});
},
};
};
性能分析 #
构建分析 #
bash
# 分析构建
turbo build --profile
# 生成分析报告
turbo build --analyze
性能报告 #
javascript
// performance-report.js
const { performance } = require('perf_hooks');
const startTime = performance.now();
module.exports = {
name: 'performance-plugin',
setup(build) {
build.onStart(() => {
console.log(`Build started at ${new Date().toISOString()}`);
});
build.onEnd(() => {
const duration = performance.now() - startTime;
console.log(`Build completed in ${duration.toFixed(2)}ms`);
});
},
};
内存分析 #
bash
# 启用内存分析
NODE_OPTIONS="--inspect" turbo dev
# 使用 Chrome DevTools 分析
# chrome://inspect
缓存分析 #
bash
# 查看缓存统计
turbo build --summarize-cache
# 输出示例
# Cache hits: 150
# Cache misses: 10
# Total time saved: 45s
调试技巧 #
详细日志 #
bash
# 启用详细日志
turbo build --log-level verbose
# 调试模式
turbo build --debug
# 输出任务图
turbo build --graph
干运行模式 #
bash
# 查看将执行的任务
turbo build --dry-run
# 输出示例
# • build @my-org/web
# • build @my-org/ui
# • build @my-org/utils
缓存调试 #
bash
# 强制重新构建
turbo build --force
# 查看缓存内容
turbo build --summarize-cache
# 清除缓存
rm -rf .turbo
模块解析调试 #
javascript
// debug-resolve.js
module.exports = {
name: 'debug-resolve',
setup(build) {
build.onResolve({ filter: /.*/ }, (args) => {
console.log(`Resolving: ${args.path}`);
console.log(` Importer: ${args.importer}`);
console.log(` Namespace: ${args.namespace}`);
return null;
});
},
};
高级配置 #
条件配置 #
javascript
// next.config.js
const isProduction = process.env.NODE_ENV === 'production';
module.exports = {
experimental: {
turbo: {
rules: {
'*.svg': {
loaders: isProduction
? ['@svgr/webpack', 'image-webpack-loader']
: ['@svgr/webpack'],
as: '*.js',
},
},
},
},
};
多环境配置 #
javascript
// next.config.js
module.exports = (phase, { defaultConfig }) => {
const config = {
experimental: {
turbo: {},
},
};
if (phase === 'phase-development-server') {
config.experimental.turbo.resolveAlias = {
'@': './src',
};
}
if (phase === 'phase-production-build') {
config.experimental.turbo.minify = true;
}
return config;
};
自定义输出 #
javascript
// next.config.js
module.exports = {
experimental: {
turbo: {
output: {
path: './build',
publicPath: '/assets/',
filename: '[name].[contenthash].js',
chunkFilename: '[name].[contenthash].chunk.js',
},
},
},
};
代码分割策略 #
动态导入 #
tsx
// 动态导入组件
import dynamic from 'next/dynamic';
const HeavyComponent = dynamic(
() => import('./HeavyComponent'),
{
loading: () => <p>Loading...</p>,
ssr: false,
}
);
export function Page() {
return (
<div>
<h1>My Page</h1>
<HeavyComponent />
</div>
);
}
预加载 #
tsx
import { preload } from 'react-dom';
function Link({ href, children }) {
const handleMouseEnter = () => {
preload(href, { as: 'script' });
};
return (
<a href={href} onMouseEnter={handleMouseEnter}>
{children}
</a>
);
}
分块策略 #
javascript
// next.config.js
module.exports = {
experimental: {
turbo: {
chunkSplitting: {
strategy: 'default',
overrides: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
priority: 10,
},
common: {
minChunks: 2,
name: 'common',
priority: 5,
},
},
},
},
},
};
服务端渲染优化 #
SSR 配置 #
javascript
// next.config.js
module.exports = {
experimental: {
turbo: {
ssr: {
external: ['react', 'react-dom'],
noExternal: ['@my-org/ui'],
},
},
},
};
流式渲染 #
tsx
// app/page.tsx
import { Suspense } from 'react';
async function SlowComponent() {
await new Promise(resolve => setTimeout(resolve, 2000));
return <div>Slow content loaded</div>;
}
export default function Page() {
return (
<div>
<h1>Fast content</h1>
<Suspense fallback={<div>Loading...</div>}>
<SlowComponent />
</Suspense>
</div>
);
}
边缘运行时 #
tsx
// app/api/route.ts
export const runtime = 'edge';
export async function GET() {
return new Response(JSON.stringify({ message: 'Hello from edge' }), {
headers: { 'Content-Type': 'application/json' },
});
}
安全配置 #
CSP 配置 #
javascript
// next.config.js
module.exports = {
async headers() {
return [
{
source: '/:path*',
headers: [
{
key: 'Content-Security-Policy',
value: "default-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline';",
},
],
},
];
},
};
环境变量安全 #
javascript
// next.config.js
module.exports = {
env: {
NEXT_PUBLIC_API_URL: process.env.API_URL,
},
experimental: {
turbo: {
env: {
// 只在构建时可用的环境变量
BUILD_TIME: new Date().toISOString(),
},
},
},
};
监控与日志 #
构建监控 #
javascript
// plugins/monitor-plugin.js
module.exports = function monitorPlugin() {
return {
name: 'monitor-plugin',
setup(build) {
const metrics = {
startTime: 0,
moduleCount: 0,
errors: [],
};
build.onStart(() => {
metrics.startTime = Date.now();
metrics.moduleCount = 0;
metrics.errors = [];
});
build.onLoad({ filter: /.*/ }, () => {
metrics.moduleCount++;
return null;
});
build.onEnd((result) => {
const duration = Date.now() - metrics.startTime;
console.log({
duration: `${duration}ms`,
modules: metrics.moduleCount,
errors: result.errors.length,
warnings: result.warnings.length,
});
});
},
};
};
错误追踪 #
javascript
// plugins/error-tracking.js
const Sentry = require('@sentry/node');
module.exports = function errorTrackingPlugin() {
return {
name: 'error-tracking',
setup(build) {
build.onEnd((result) => {
result.errors.forEach(error => {
Sentry.captureException(new Error(error.text));
});
});
},
};
};
下一步 #
现在你已经掌握了 Turbopack 的高级用法,接下来学习 最佳实践 了解如何在生产环境中高效使用 Turbopack!
最后更新:2026-03-28