Serveeless之Convex学习记录

Aron Lv3

什么是Serverless

Serverless(无服务器计算)是一种云计算模式:开发者只需编写代码(通常是函数),云提供商(如AWS、阿里云、腾讯云)自动管理服务器、扩展和维护。
你不用管服务器采购、运维、负载均衡等,只按实际使用量付费(不运行不收费)。

我为什么要了解Serverless

我出身于移动端开发者,长期以来,我理解不了Serverless模式。经过近期的一些契机,我逐渐解开了Serverless的神秘面纱。

首先,Serverless并不代表“没有服务端”,并不代表离线应用。它只是替代了传统意义样的服务端开发模式。
一直以来,我们开发服务端的流程往往是,先买云服务商的计算资源,再用类似于Java这种语言部署一套类似于Spring的框架,给前端提供接口,编写文档,与前端联调。
Serverless彻底改变了这一点。它带给我的优势主要在于,我不需要购买服务器我不需要关心运维我可以自己一个人开发一整套项目,包括前后端。

Convex和Serverless的关系是什么

Convex是一个现代Serverless后端平台(Backend as a Service,BaaS),专为全栈开发者(尤其是React/Next.js + TypeScript用户)设计,让你用纯TypeScript编写整个后端,包括数据库、函数、认证和实时同步。

配合React和React Native使用,我可以用TypeScript构建一整套系统。

怎么使用Convex

以React Native项目为例。首先你当然需要一个convex账号,注册后,你相当于拥有了自己的服务器,拥有了自己的文件存储系统,拥有了数据库等一系列后端开发所需要的东西。

初始化

在RN项目目录下执行npx convex dev,这会自动为你的项目添加convex配置,将你的项目跟convex建立关联,在项目中增加convex文件夹,并添加convex服务端开发所需要的一些插件包,这其中就是你的后端代码所在处,开发语言同样是TypeScript。

命令执行完毕之后,你的项目目录大概会是这个样子的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
...其他项目文件
convex
├── _generated
│ ├── api.d.ts
│ ├── api.js
│ ├── dataModel.d.ts
│ ├── server.d.ts
│ └── server.js
├── auth.config.ts
├── auth.ts
├── file.ts
├── http.ts
├── profile.ts
├── README.md
├── ResendOTP.ts
├── schema.ts
├── testFunctions.ts
└── tsconfig.json

理解目录结构

现在,你的项目中多了一个convex文件夹。其中,_generated目录是convex自动生成的类型系统,目前可以不用管。
auth.config.jsauth.ts是项目的鉴权配置,目前我这个项目比较简单,配合Resend实现了邮箱验证码鉴权。
多说一嘴,现在很多项目开始使用Clerk和Auth0来实现用户鉴权,不再自己编写用户鉴权代码,这些都是现在很可靠的鉴权认证方案。我没有使用这些服务,用的是convex自己的Convex Auth文档在这里

其他的文件,比如profile.tsfile.ts以及testFunctions.ts,都是后期自己加的,这些文件可以理解为一个个Controller,内部会导出一个个函数,就相当于一个个的API接口。
schema.ts定义数据库表结构。

理解Convex的用法

这是官方给的示例代码,这个myQueryFunction相当于一个HTTP查询接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// convex/myFunctions.ts
import { query } from "./_generated/server";
import { v } from "convex/values";

/// 增删改查,query就是查询方法
export const myQueryFunction = query({
/// 定义这个API接口的入参,这里有两个参数,分别是数字和字符串
/// 假如类型错误,或者参数不对,会直接报错
args: {
first: v.number(),
second: v.string(),
},

// 方法体,也就是这个接口的实际代码逻辑
handler: async (ctx, args) => {
/// 从数据库里面读取数据
/// 关于数据库的读写部分可以看看 https://docs.convex.dev/database/reading-data.
const documents = await ctx.db.query("tablename").collect();

/// 这些打印日志会出现在convex后台日志里面,排查的时候可以看
console.log(args.first, args.second);

/// 把查到的数据返回给前端
return documents;
},
});

怎么调用这个接口呢?

1
2
3
4
5
6
/// 在我任意一个RN页面中,使用这个hook,假设这里是/app/_layout.tsx
/// 注意这里的数据是实时的,当数据库里面的查询结果发生变化后,我们能立即看到最新的结果
const data = useQuery(api.myFunctions.myQueryFunction, {
first: 10,
second: "hello",
});

这种感觉就好像左手倒右手,convex目录下是你的服务端逻辑,其他地方是你的客户端逻辑,除了服务端资源外,你还节省了大量的调试时间。

Convex部署

Convex的部署和生效非常简单,编写好convex函数后,执行npx convex dev即可在dev环境上应用最新的代码。
它立即把最新的函数,以及数据库表结构,都部署到了dev环境上。就是这么简单。

Convex数据库表结构

Convex数据库表结构是基于MongoDB的,你可以在schema.ts文件中定义你的数据库表结构。
首先,新建convex/schema.ts文件,并在里面使用defineSchema方法定义你的数据库表结构。
比如,假设你要定义一个users表,里面有idnameemail等字段,你可以这样写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// convex/schema.ts
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";

export default defineSchema({
users: defineTable({
name: v.string(),
email: v.string(),
}).index('by_name', ['name']),
profile: defineTable({
userId: v.id('users'),
avatar: v.string(),
}).index('by_userId', ['userId']),
});

// 我得到了一张users表,里面有id、name、email等字段,并配置了一个索引by_name,用于根据name查询用户。
// 我还得到了一张profile表,里面有id、userId、avatar等字段,并配置了一个索引by_userId,用于根据userId查询用户的个人信息。其中userId是users表的外键,用于关联用户。

Convex核心优势在哪里

我为什么想要学习Convex?
首先,它最主要的优势还是开发效率高,对新手友好。我现在可以很快就搭建一个系统,而不需要购买服务器,也不需要关心运维。
此外,它的所有请求都是实时的,所有的hook都是实时的,这意味着上面这个例子里面的data会随着数据库里面的数据实时刷新!简单省事。
基于此,我可以快速搭建我自己的一套系统。
除此之外,举一反三,我开始理解了比如AWS Lambda的概念,以及它的优势。我觉得它可以帮助我更快理解Serverless的概念。

  • 标题: Serveeless之Convex学习记录
  • 作者: Aron
  • 创建于 : 2025-12-27 14:19:15
  • 更新于 : 2026-01-28 16:34:52
  • 链接: https://likeso.github.io/2025/12/27/introducing-convex/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论