Skip to content

常见任务和故障排除

本指南涵盖常见的开发任务和问题解决方案。

步骤:

  1. packages/api/src/routers/ 创建新文件:
packages/api/src/routers/posts.ts
import { z } from 'zod'
import { publicProcedure, router } from '../index'
export const postsRouter = router({
list: publicProcedure.query(async () => {
// 实现逻辑
})
})
  1. packages/api/src/routers/index.ts 中注册:
import { postsRouter } from './posts'
export const appRouter = router({
posts: postsRouter
// ... 其他路由
})
  1. 在前端使用:
const { data } = trpc.posts.list.useQuery()

步骤:

  1. packages/db/src/schema/ 定义新表:
packages/db/src/schema/posts.ts
import { pgTable, text, timestamp } from 'drizzle-orm/pg-core'
export const posts = pgTable('posts', {
id: text('id').primaryKey(),
title: text('title').notNull(),
content: text('content'),
createdAt: timestamp('created_at').defaultNow()
})
  1. packages/db/src/schema/index.ts 导出:
export * from './posts'
  1. 运行 pnpm run db:push 应用变更

步骤:

  1. apps/web/src/components/ 创建组件:
apps/web/src/components/PostList.tsx
import { trpc } from "@/utils/trpc";
export function PostList() {
const { data } = trpc.posts.list.useQuery();
return (
<div>
{data?.map(post => (
<div key={post.id}>{post.title}</div>
))}
</div>
);
}
  1. 在页面中使用:
import { PostList } from "@/components/PostList";
export default function Page() {
return <PostList />;
}

问题: TypeScript 类型检查失败

解决方案:

Terminal window
# 检查所有类型
pnpm run check-types
# 检查特定包
cd packages/api && pnpm run check-types

常见原因:

  • 缺少类型定义
  • 导入路径错误
  • 环境变量类型不匹配

问题: 数据库连接或查询失败

解决方案:

Terminal window
# 打开数据库管理界面
pnpm run db:studio
# 检查数据库连接
# 验证 DATABASE_URL 环境变量

常见原因:

  • 数据库未启动
  • 连接字符串错误
  • 表不存在(需要运行迁移)

问题: 环境变量未正确加载

解决方案:

  1. 检查 .env 文件是否存在
  2. 验证 packages/env/src/server.ts 中的配置
  3. 确保环境变量在 turbo.json 中声明

常见原因:

  • .env 文件未创建
  • 环境变量名称拼写错误
  • 类型验证失败

问题: 用户无法登录或会话丢失

解决方案:

  1. 检查 BETTER_AUTH_SECRET 是否正确设置
  2. 验证 BETTER_AUTH_URLCORS_ORIGIN 配置
  3. 检查浏览器 Cookie 设置

常见原因:

  • Cookie 被阻止
  • CORS 配置错误
  • 认证密钥不匹配

问题: 在普通 Chrome 中走 OIDC 授权流程时失败(无痕模式正常)

这通常是因为浏览器残留了旧的 Cookie、Draft Mode 状态或 Vercel Toolbar 注入的参数,干扰了正常的重定向链。按以下步骤逐一排查:

1. 清除 IAM 站点数据

需要分别清除前端后端两个站点的数据:

  • 打开 chrome://settings/content/all
  • 搜索 iam-nodejs-web.vercel.app,点进去 → 删除数据
  • 搜索 iam-nodejs-server.vercel.app,点进去 → 删除数据

更快的方法:分别打开两个站点的任意页面,点击地址栏左侧的”网站信息”图标 → 网站设置删除数据

2. 关闭 Vercel Toolbar

如果请求参数中出现了 __vercel_toolbar=1,说明 Vercel Toolbar 处于激活状态:

  • 在页面右下角找到 Vercel Toolbar 并关闭
  • 如果关闭后请求中仍然带有该参数,打开 DevTools → ApplicationCookies,手动删除 __vercel_toolbar Cookie

3. 退出 Draft Mode / Preview 状态

如果请求头中出现 x-vercel-draft-status: 1,说明页面处于 Draft/Preview 模式:

  • 打开站点首页,寻找”Exit Draft Mode”入口并点击退出
  • 如果找不到该入口,打开 DevTools → ApplicationCookies,删除该站点的所有 Cookie,然后刷新页面

4. 关闭所有旧标签页

关闭所有与 OIDC 流程相关的标签页,包括:

  • /oauth-login 登录页
  • /consent 授权确认页
  • OIDC Debugger 页面
  • 任何其他残留的测试页面

5. 从头发起新的 OIDC 流程

新开一个标签页,从第三方客户端重新发起完整的 OIDC 授权流程。不要从浏览器历史记录中恢复、刷新旧页面或使用后退按钮继续之前的流程。

问题: 构建失败或找不到模块

解决方案:

Terminal window
# 清理并重新安装
rm -rf node_modules
pnpm install
# 清理构建缓存
pnpm run build --force

常见原因:

  • 依赖未正确安装
  • workspace 依赖未构建
  • 缓存问题

Turborepo 自动缓存构建结果:

  • 只重新构建变更的包
  • 加速 CI/CD 流程
  • 减少构建时间

使用索引:

import { index } from 'drizzle-orm/pg-core'
export const posts = pgTable(
'posts',
{
id: text('id').primaryKey(),
authorId: text('author_id')
},
(table) => ({
authorIdIdx: index('author_id_idx').on(table.authorId)
})
)

避免 N+1 查询:

// 不好 - N+1 查询
const posts = await db.select().from(posts)
for (const post of posts) {
const author = await db.select().from(user).where(eq(user.id, post.authorId))
}
// 好 - 使用 join
const postsWithAuthors = await db.select().from(posts).innerJoin(user, eq(posts.authorId, user.id))

使用 React Query 缓存:

const { data } = trpc.posts.list.useQuery(undefined, {
staleTime: 5 * 60 * 1000, // 5 分钟
cacheTime: 10 * 60 * 1000 // 10 分钟
})

代码分割:

// 动态导入
const HeavyComponent = dynamic(() => import("./HeavyComponent"), {
loading: () => <div>Loading...</div>,
});

批量操作:

// 批量查询
const items = await db.select().from(items).where(inArray(items.id, ids))

分页:

const posts = await db
.select()
.from(posts)
.limit(pageSize)
.offset(page * pageSize)
  1. 代码组织: 保持代码模块化和可维护
  2. 类型安全: 充分利用 TypeScript 类型系统
  3. 错误处理: 提供清晰的错误消息
  4. 测试: 编写单元测试和集成测试
  5. 文档: 保持文档更新

如果遇到问题:

  1. 检查相关指南文档
  2. 查看项目 README
  3. 搜索 GitHub Issues
  4. 联系开发团队