$catSERPAPI||~18 min

Vercel结合Turso与GitHub现代全栈网站搭建实战指南

advertisement

Vercel结合Turso与GitHub:我的现代全栈网站搭建踩坑实录

为啥我要折腾这套组合?

说实话,之前我一直在用传统的方式部署项目——买个云服务器,装个Nginx,手动配SSL证书,数据库用MySQL或者PostgreSQL。听起来挺稳的是吧?但实际用起来,痛点真的太多了。

首先,服务器要自己维护,系统补丁要打,Nginx配置要调,SSL证书过期了还得手动续。更头疼的是数据库连接池的问题——有一阵子我的博客突然流量上来了,结果MySQL连接池直接被打满,网站卡得跟幻灯片似的。我临时手忙脚乱地加了个Redis做缓存,又折腾了半天PgBouncer连接池中间件,才勉强扛住。

还有全球访问的问题。我服务器放在国内,海外用户反馈说打开页面要好几秒,这体验实在太差了。

后来我偶然了解到了 Vercel + Turso + GitHub 这套组合,试了一下,真的回不去了。这篇文章就是我从零开始搭建的完整记录,包括我踩过的各种坑,希望对你有帮助。

这三个东西分别是啥?

Vercel:部署神器

Vercel 简单来说就是一个专门给前端和全栈应用用的云平台。你把代码推到GitHub,它自动帮你构建、部署,还给你一个 .vercel.app 的域名直接访问。全球几十个边缘节点,国内外访问速度都不错。

最让我惊喜的是它对 Next.js 的支持简直是原生级别的——Serverless Functions、Edge Functions 都能无缝运行。而且2026年它全面拥抱了AI,推出了 v0、AI SDK 这些工具,在上面做AI驱动的网站变得特别方便。

Turso:边缘数据库的黑马

这是我踩坑最多也最惊喜的部分。传统的关系型数据库在 Serverless 环境下有个致命问题:无状态函数频繁触发,数据库连接池瞬间就耗尽了。

Turso 基于 libSQL(SQLite 的开源分支),它把数据库文件复制到全球边缘节点,查询走的是 HTTP 协议而不是传统的 TCP 长连接。这意味着什么?读操作延迟降到了毫秒级,高并发下依然稳如老狗。

我第一次用 Turso 的时候还犯了个低级错误——以为它跟普通数据库一样用TCP连接,结果怎么都连不上。后来才搞明白,它默认就是 HTTP 模式,要用 @libsql/client/http 这个包。

GitHub Actions:自动化的核心

这个不用多说了,代码推上去,自动触发 Vercel 构建部署,全自动化的闭环。push 一下代码,一分钟不到线上就更新了,比我自己手动 ssh + git pull + pm2 restart 的时代效率高了不知道多少倍。

技术选型对比:我为啥不继续用老方案?

老方案(虚拟机 + 集中式数据库)的痛点:

  • 手动管理服务器、配置 Nginx 反向代理、处理 HTTPS 证书,光是这些运维工作就能消耗掉大量时间
  • 数据库连接池容易被高并发打满,需要额外引入 Redis 或 PgBouncer
  • 全球用户访问时,物理距离导致的网络延迟难以克服

新方案(Vercel + Turso + GitHub)的优势:

  • 无需管理服务器,应用按需自动扩缩容,从 0 并发到 10 万并发不用改架构
  • 通过 Turso 的嵌入式副本技术,数据库直接运行在离用户最近的边缘节点,读取延迟接近本地文件
  • 只需一次 git push,Vercel 便自动完成构建、预览发布与正式部署

实战:手把手搭一个留言板系统

我选了一个 Next.js 的留言板作为示例,因为它足够简单又能展示全栈能力。

第一步:项目初始化

确保你装了 Node.js 18+,然后:

bash
1
# 创建 Next.js 项目
2
npx create-next-app@latest edge-guestbook
3
 
4
# 进入项目目录
5
cd edge-guestbook
6
 
7
# 安装 Turso 的 libSQL 客户端
8
npm install @libsql/client

第二步:配置 Turso 数据库

先去 turso.tech 注册账号,然后安装 CLI:

bash
1
# 安装 Turso CLI
2
curl -sSfL https://get.tur.so/install.sh | bash
3
 
4
# 登录
5
turso auth login
6
 
7
# 创建数据库
8
turso db create guestbook-db
9
 
10
# 获取连接 URL(后面配环境变量要用)
11
turso db show guestbook-db --url
12
 
13
# 输出示例: libsql://guestbook-db-<your-name>.turso.io
14
 
15
# 创建鉴权 Token
16
turso db tokens create guestbook-db

然后连接数据库建表:

bash
1
turso db shell guestbook-db

在 shell 里执行:

sql
1
CREATE TABLE messages (
2
  id INTEGER PRIMARY KEY AUTOINCREMENT,
3
  username TEXT NOT NULL,
4
  content TEXT NOT NULL,
5
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
6
);
7
 
8
.quit

踩坑提醒:我第一次建表的时候忘了 AUTOINCREMENT,后来插入数据时 id 字段老是报错,排查了半天才发现。

第三步:写业务逻辑

新建 app/api/messages/route.ts

typescript
1
import { createClient } from '@libsql/client/http';
2
import { NextResponse } from 'next/server';
3
 
4
const client = createClient({
5
  url: process.env.TURSO_DATABASE_URL!,
6
  authToken: process.env.TURSO_AUTH_TOKEN!,
7
});
8
 
9
export async function GET() {
10
  try {
11
    const result = await client.execute('SELECT * FROM messages ORDER BY created_at DESC');
12
    return NextResponse.json(result.rows);
13
  } catch (error) {
14
    console.error('Database query failed:', error);
15
    return NextResponse.json({ error: 'Failed to fetch messages' }, { status: 500 });
16
  }
17
}
18
 
19
export async function POST(request: Request) {
20
  try {
21
    const { username, content } = await request.json();
22
    await client.execute({
23
      sql: 'INSERT INTO messages (username, content) VALUES (?, ?)',
24
      args: [username, content],
25
    });
26
    return NextResponse.json({ success: true }, { status: 201 });
27
  } catch (error) {
28
    console.error('Insert failed:', error);
29
    return NextResponse.json({ error: 'Failed to post message' }, { status: 500 });
30
  }
31
}

前端页面 app/page.tsx

tsx
1
'use client';
2
 
3
import { useState, useEffect } from 'react';
4
 
5
interface Message {
6
  id: number;
7
  username: string;
8
  content: string;
9
  created_at: string;
10
}
11
 
12
export default function Home() {
13
  const [messages, setMessages] = useState<Message[]>([]);
14
  const [username, setUsername] = useState('');
15
  const [content, setContent] = useState('');
16
 
17
  useEffect(() => {
18
    fetch('/api/messages')
19
      .then((res) => res.json())
20
      .then((data) => setMessages(data));
21
  }, []);
22
 
23
  const handleSubmit = async (e: React.FormEvent) => {
24
    e.preventDefault();
25
    if (!username || !content) return;
26
 
27
    const res = await fetch('/api/messages', {
28
      method: 'POST',
29
      headers: { 'Content-Type': 'application/json' },
30
      body: JSON.stringify({ username, content }),
31
    });
32
 
33
    if (res.ok) {
34
      setContent('');
35
      const updatedMsgs = await (await fetch('/api/messages')).json();
36
      setMessages(updatedMsgs);
37
    }
38
  };
39
 
40
  return (
41
    <main className="max-w-2xl mx-auto p-6">
42
      <h1 className="text-3xl font-bold mb-8">边缘留言板</h1>
43
      <form onSubmit={handleSubmit} className="mb-8 space-y-4">
44
        <input
45
          type="text"
46
          placeholder="你的名字"
47
          value={username}
48
          onChange={(e) => setUsername(e.target.value)}
49
          className="w-full p-2 border rounded"
50
        />
51
        <textarea
52
          placeholder="写下你的留言..."
53
          value={content}
54
          onChange={(e) => setContent(e.target.value)}
55
          className="w-full p-2 border rounded"
56
        />
57
        <button type="submit" className="bg-blue-600 text-white px-4 py-2 rounded">
58
          提交留言
59
        </button>
60
      </form>
61
      <div className="space-y-4">
62
        {messages.map((msg) => (
63
          <div key={msg.id} className="border p-4 rounded shadow-sm">
64
            <p className="font-semibold">{msg.username}</p>
65
            <p>{msg.content}</p>
66
            <p className="text-sm text-gray-500 mt-2">{msg.created_at}</p>
67
          </div>
68
        ))}
69
      </div>
70
    </main>
71
  );
72
}

本地开发时创建 .env.local

bash
1
TURSO_DATABASE_URL="你的_TURSO_URL"
2
TURSO_AUTH_TOKEN="你的_TURSO_TOKEN"

运行 npm run dev 就能在本地看到效果了。

第四步:推到 GitHub 并部署到 Vercel

bash
1
git init
2
git add .
3
git commit -m "Initial commit: Vercel + Turso stack"
4
git remote add origin https://github.com/your-username/edge-guestbook.git
5
git push -u origin main

然后去 Vercel Dashboard,点 "Add New..." -> "Project",选择你刚创建的仓库。Vercel 会自动识别 Next.js 项目。

关键步骤:配置环境变量

在 Vercel 的部署设置页面,找到 "Environment Variables":

  • 添加 TURSO_DATABASE_URL
  • 添加 TURSO_AUTH_TOKEN

这里有个血泪教训:2026年4月 Vercel 出过一次安全事件,第三方AI工具 Context.ai 被入侵,攻击者获取了部分 Vercel 员工权限,访问了一些没标记为 "Sensitive" 的环境变量。所以!凡涉及数据库凭证、API密钥,在 Vercel 后台配置时,必须勾选 Sensitive 选项。标记后这些值在面板、日志中都会被加密隐藏。

点击部署,不到一分钟你的网站就上线了。

最佳实践和注意事项

数据库迁移管理

开发初期我直接用 turso db shell 手动建表,但在正经项目中,建议引入版本化的迁移工具。可以结合 GitHub Actions,在代码合并到主分支触发部署前,自动运行 Turso 的迁移脚本,确保数据库结构和代码保持一致。

架构的适用边界

Vercel + Turso 是高度分布式的无状态架构,非常适合读多写少、需要极速响应的 Web 应用,比如博客、内容站、AI 聊天界面、SaaS 工具。

但如果你在做一个需要极其复杂的跨表事务处理的系统(比如大型金融结算),传统的集中式数据库加上长连接池可能仍是更稳妥的选择。技术选型没有银弹,关键是找到适合自己场景的方案。

总结

这套 Vercel + Turso + GitHub 的工作流确实改变了我对全栈开发的认知。以前我花大量时间在运维和服务器管理上,现在 git push 一下就搞定了部署,精力完全放在业务逻辑和用户体验上。

更重要的是,它让我看到了 Web 架构演进的方向——从单点集中式,走向无服务器化、边缘化和智能化。如果你也想试试现代全栈开发,这套组合绝对值得入手。

advertisement

Vercel结合Turso与GitHub现代全栈网站搭建实战指南 — AI Hub