Vite+ 全栈方案:用一套工具链同时开发 Web 与移动端
译注:本文编译自 dev.to 文章《Vite Plus Full Stack cho phát triển Web & Mobile với AI Agents》,作者 Max Vien。原文介绍了一个基于 Vite+ 的全栈 monorepo 方案,旨在用统一工具链覆盖 Web 与移动端开发,并集成 AI 编码 Agent。原文链接见文末。
背景:工具链碎片化的困境
开发一个同时需要网站和手机应用的产品,往往意味着打开二十个标签页:Web 框架、移动端框架、UI 套件、API 层、校验、认证、数据库、邮件、缓存、文件存储、日志、本地 Docker 环境、服务器部署方案,还要再加一个能读懂仓库、不会自行发明另一套架构的 AI Agent。
几周之后,这堆工具勉强能互相通信了,但最初的想法已经凉了。技术选型开始变得像在做工程,而最重要的东西——产品本身——却还没动手。
作者提出的方案是跳过这场"技术采购":一个面向 Web 和移动端的 monorepo,由 Vite+ 组织。工具本身已经足够好,把它们互相介绍认识,开发者就能专注于交付功能。
一个约定:100 stars 即开源
作者设定了一个门槛:当仓库达到 100 stars,他将构建并发布该项目,采用 MIT 许可证。免费使用、免费修改、免费直接用于自己的产品。没有课程、没有付费墙、没有挡在真正需要的东西前面的企业版套餐。
作者认为,一个 star 只需两秒,它的含义是:"请构建那些无聊的系统部分,让我去构建有趣的部分。"
仓库地址:https://github.com/VienDinhCom/vite-plus-full-stack
技术栈构成
一个 monorepo
Vite+ 是统一在 vp 命令背后的工具链,整合了以往需要手工拼接的多个工具:Vite、Rolldown、Vitest、tsdown、Oxlint、Oxfmt 和 Vite Task。免费,MIT 许可证。
一个配置文件,一套命令:vp install、vp dev、vp check、vp test、vp build、vp run。
vp check 在一次运行中完成格式化、lint 和类型检查,并自动修复它能修复的问题。测试复用应用的 resolve 和 transform 配置,测试运行器兼容 Jest API,默认隔离测试,甚至可以在真实浏览器中运行测试。
关于速度,Vite+ 给出的数据相当具体:核心用 Rust 编写,生产构建可比 webpack 快 40 倍,lint 比 ESLint 快约 50 到 100 倍,格式化比 Prettier 快 30 倍,热模块替换依然近乎即时。在 monorepo 中,Vite Task 会缓存任务并按依赖顺序运行各 package。
Web 与移动端,同一门语言
TanStack Start 负责 Web 应用:基于 TanStack Router 的全栈 React,支持类型安全路由、服务端渲染、流式传输和 server functions。路由、loader 和 link 各就各位,Start 补充了服务端部分。server function 就写在调用它的代码旁边,校验器守在入口。
Expo 负责移动端应用:这是 React Native 官方团队推荐的框架,覆盖 iOS、Android 和 Web,拥有庞大的原生 API 生态。基于文件的路由,类型化路由。会 React 就能发布手机应用,只有某个界面真正需要时才会用到 Swift 或 Kotlin。
同一门 TypeScript,两个客户端,一个产品。
UI 归自己所有
Tailwind CSS 同时用于 Web 和移动端。工具类直接写在标记中,再组合成真正想要的设计。生产构建会移除从未使用过的 CSS。
shadcn/ui 用于 Web 组件:可访问、可组合,直接复制进仓库供自行修改。Button 是自己的,库的发布节奏不是你的老板。
React Native Reusables 用于移动端:把 shadcn/ui 带到 React Native,用 Nativewind 或 Uniwind 做样式。手机 UI 和网站 UI 可以保持同一套视觉语言。
一个 API,两个客户端
oRPC 是定义和实现服务端 API 的地方。两个客户端都以端到端类型调用 API。当合作方、文档或另一种语言需要普通 HTTP 契约时,OpenAPI 已经就绪。它提供 TanStack Start 和 Expo 的适配器、与 Better Auth 的集成,以及面向 TanStack Query 的一等 helper。
TanStack Query 管理服务端状态。组件声明需要什么数据,缓存自动去重进行中的请求、重试、后台重新获取,并在网络跟上时保留屏幕上的过期数据。Mutation 可以先更新 UI 再与服务器同步。Web 和移动端用同一套做法。
Schema 走遍各处
Zod 是 schema 语言:TypeScript 优先、无依赖、足够小,服务端和客户端都能跑。描述一次 payload,在数据进入时解析,从同一个对象推断类型。oRPC 通过 Standard Schema 接收 Zod,因此 API 契约和校验器实际上是同一个东西。
T3 Env 用同一套 Zod schema 解析环境变量。缺少 key 时应用在启动时立即失败,并给出可读的消息,而不是跑完三个界面才崩溃。服务端变量和客户端变量分开,从客户端读取服务端 secret 会故意抛出错误。
认证、数据与真实产品的其余部分
Better Auth 直接位于应用代码中:邮箱密码、session、社交登录、组织、角色、双因素、passkey,以及一长串插件。配置是一个可以在 pull request 中直接审查的文件。
Drizzle ORM 用 TypeScript 管理 Postgres:schema、查询和迁移。行级安全(RLS)位于数据库内。用户只能看到自己的行,因为 Postgres 这么说,即使 handler 忘了写 where。
围绕核心的服务:
- React Email:用 React 组件编写邮件,通过正在使用的 provider 发送。
- Redis:保存缓存、速率限制和短期状态。
- Twilio:负责电话部分。
- Amazon S3:生产环境存储文件。在笔记本上,RustFS 提供相同的 S3 API,上传代码无需改动。RustFS 是开源项目,Apache 2.0 许可,用 Rust 编写。
- OpenTelemetry:一次性收集 traces、metrics 和 logs,之后导出到任意后端。oRPC 可以跨 procedure 调用记录这些 span。
先笔记本,后服务器
Docker 运行本地服务:Postgres、Redis、RustFS 和 Mailpit。Mailpit 是一个带 Web 收件箱的小型 SMTP 服务器,能渲染 HTML、检查链接、评估垃圾邮件评分,并提供测试用 API。密码重置邮件会留在本机,直到决定让真实收件箱接收它。
对于 VPS,Kamal 把容器化应用部署到普通 Ubuntu 服务器上:零停机部署、滚动重启和附属服务。给它 IP 地址和 SSH key,它安装 Docker 然后发布。这也是 37signals 曾用来把应用部署到自有硬件上的方式。
也可以部署在已有账号的地方:Amazon AWS、Vercel、Google Cloud、Railway、Fly.io 等。TanStack Start 在部署目标变化时保持路由和服务端边界不变。Kamal 是 VPS 路线,整个技术栈保持可移植。
Agent 知道自己在哪
OpenCode 是开源编码 Agent,可在终端、桌面应用或 IDE 中运行,支持 Claude、GPT、Gemini、本地模型或任意 75 个以上 provider。它不保存代码或上下文。
三个工具帮助它始终知道自己在仓库中的位置:
- CodeGraph:构建本地代码知识图谱,文件变化时同步。Agent 寻找路径时消耗更少 token。图谱留在本机,OpenCode 已支持它。
- Ponytail:引导 Agent 做最小但能解决问题的改动。最好的代码是不需要写的代码。
- DBHub:面向 Postgres 和其他数据库的省 token MCP server。默认只有两个工具,为任务留出上下文窗口。提供只读模式、行数限制和超时,以防某个问题不该变成一次迁移。
用它做什么
用它,交付功能。
界面是 React,样式是 Tailwind,组件归自己所有,payload 是 Zod schema,调用是 oRPC,缓存是 TanStack Query,session 是 Better Auth,行是 Postgres(背后有 RLS),邮件是 React 组件,文件在 S3 上,trace 由 OpenTelemetry 收集,Agent 能看到图谱、数据库,以及让它少写代码的指令。
这些工具中的每一个本来就已经很好。缺的是它们之间的统一。
轮到你了
如果这是你会花一个周末拼起来、然后持续维护多年的系统,请投票。
100 stars。我来构建。MIT 许可证。免费。
立即 Star VienDinhCom/vite-plus-full-stack