Bolt.new 修复教程 2026:常见报错与解决方案

Bolt.new 出原型很快,但生成的代码经常在几个固定地方翻车:useEffect 无限循环、部署失败、数据库连接爆掉、N+1 查询拖慢页面。这篇教程按出现频率高低排序,每个问题给出诊断方法和可直接复制的修复代码。预算 2–3 小时跑一遍,能解决绝大多数线上事故。
常见问题速查
| 问题 | 症状 | 修复难度 |
|---|---|---|
| useEffect 无限循环 | 浏览器卡死、控制台疯狂打日志 | 简单 |
| 部署失败 | 本地正常、线上报错 | 中等 |
| 数据库连接错误 | "Too many connections" | 中等 |
| N+1 查询 | 页面慢、Network 面板大量重复请求 | 中等 |
| 认证失效 | 刷新后掉登录 | 中等 |
| 缺少安全防护 | 任何人都能改数据 | 困难 |
问题 1:useEffect 无限循环
原因:依赖数组写错或者漏写,effect 每次渲染都跑,跑完又触发新的渲染。
诊断:F12 打开控制台,看有没有「Maximum update depth exceeded」。
// 错误:没有依赖数组,每次渲染都跑
useEffect(() => {
fetchData().then(setData);
});
// 正确:空数组,只在挂载时跑一次
useEffect(() => {
fetchData().then(setData);
}, []);
// 正确:依赖 userId,只在它变化时跑
useEffect(() => {
fetchUserData(userId).then(setData);
}, [userId]);
另一种常见错法是「在渲染过程中 setState」:
// 错误:渲染中直接 setState
function MyComponent({ items }) {
const [sorted, setSorted] = useState([]);
setSorted(items.sort()); // 会无限循环
// 正确:用 useMemo
const sorted = useMemo(() => items.sort(), [items]);
}
Bolt.new 专用技巧:让 Bolt.new「审计所有 useEffect 的依赖数组」,它一般能自己发现。但别全信,手工再过一遍只要 15 分钟。
问题 2:部署失败
Bolt.new 应用在编辑器里跑得好好的,部署就崩。原因通常是 dev server 比 production build 宽松,放过了一些错误。
环境变量没设:
# 检查项目里用了哪些环境变量
grep -r "process.env" --include="*.ts" --include="*.tsx" src/
每个都要在 Vercel / Netlify 后台配上,缺一个都可能让构建静默失败。
TypeScript 错误:dev server 经常忽略类型错误,production 不会:
npx tsc --noEmit
大小写敏感的 import 路径:macOS 默认大小写不敏感,Linux 服务器是敏感的:
// macOS 能跑,Linux 报错
import { UserCard } from './usercard';
// 正确:完全匹配文件名
import { UserCard } from './UserCard';
问题 3:数据库连接错误
症状是少人用没事,几个人同时用就「Too many connections」。
根因:Bolt.new 每个请求都新建一个数据库连接,没有复用。
Supabase 的修复:
// lib/supabase.ts
import { createClient } from '@supabase/supabase-js';
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!;
const supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!;
// 全局只创建一次,到处复用
export const supabase = createClient(supabaseUrl, supabaseKey);
然后所有文件 import 这一个实例,而不是各自调 createClient。
缺少索引:50 行数据看不出来,5000 行就慢到不能用:
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_orders_user_id ON orders(user_id);
CREATE INDEX idx_orders_created_at ON orders(created_at);
问题 4:N+1 查询
打开 Network 面板,刷新一个列表页。如果每个 item 都发一个请求,就是 N+1。
修复方法是改写成一次性 join 查询,或者用 Supabase 的嵌套 select:
// 错误:在循环里查
const orders = await supabase.from('orders').select('*');
for (const order of orders) {
const user = await supabase.from('users').select('*').eq('id', order.user_id);
}
// 正确:嵌套 select 一次拉完
const { data } = await supabase
.from('orders')
.select('*, users(*)');
问题 5:认证失效
刷新页面就掉登录,几乎一定是 token 没正确持久化。Bolt.new 默认有时会把 session 存在 memory 里。
const supabase = createClient(url, key, {
auth: {
persistSession: true,
storage: typeof window !== 'undefined' ? window.localStorage : undefined,
},
});
问题 6:缺少安全防护
最危险的一类问题。Bolt.new 生成的 API 路由经常不验身份,任何人构造请求都能改数据。
// 错误:不验证就直接写
export async function POST(req: Request) {
const { userId, content } = await req.json();
await supabase.from('posts').insert({ user_id: userId, content });
}
// 正确:服务端拿真实用户
export async function POST(req: Request) {
const { data: { user } } = await supabase.auth.getUser();
if (!user) return new Response('Unauthorized', { status: 401 });
const { content } = await req.json();
await supabase.from('posts').insert({ user_id: user.id, content });
}
数据库层一定要开 RLS(Row Level Security),双保险。
完整自检清单
| 检查项 | 命令或动作 |
|---|---|
| 所有 useEffect 都有依赖数组 | 手动 grep useEffect |
| 环境变量全配齐 | grep -r "process.env" src/ |
| TypeScript 通过 | npx tsc --noEmit |
| 数据库连接单例 | 只 import 一个 client |
| 关键列有索引 | 查 EXPLAIN |
| API 路由都验身份 | 手动审查 |
| RLS 全开 | 数据库后台检查 |
什么时候放弃修复
如果项目超过 10000 行、bug 出在底层架构(比如整个状态管理都乱)、修一个出三个,那不如重写。重写时把 Bolt.new 当生成骨架的工具,复杂逻辑切到 Cursor 或 Claude Code 写。
讨论可以去 V2EX 的「编程」节点和 掘金,搜「Bolt.new bug」能看到不少国内开发者的实战记录。