跳转到内容
Supastack
CN
主题
登录获取 Supastack
全部文章

如何用 Next.js 与 Expo 构建 Web + 移动端 SaaS (Monorepo 实战指南)

跨端 SaaS 架构实战:在 pnpm monorepo 中统一编排 Next.js 16 与 React Native Expo,共享 Better Auth 与 Drizzle ORM 数据层。

Noah Zixin Zhang约 3 分钟阅读

如何在一个 monorepo 中让 Next.js 和 Expo 共享代码?

这取决于你的模块边界与打包工具配置。最稳健的架构是使用 pnpm 与 Turborepo 将共享的数据模型、校验模式与 API 契约隔离在无头内部包中。Next.js 16 服务端通过 Node/Edge 运行时直接运行 Drizzle ORM,而 Expo 移动端通过类型化 HTTP 接口通信,并利用 expo-secure-store 原生持久化认证凭证。supastack 开箱提供了这套完整工程配置,彻底解决了 Metro 与 Turbopack 之间的打包冲突。

跨端 SaaS 最难啃的骨头:打包工具的裂痕

每位 SaaS 创始人都知道,借助系统级推送通知与手机主屏幕入口,移动 App 能大幅提升用户粘性、复购率与日活数据。然而,将 Next.js 与 React Native Expo 塞进同一个 monorepo 通常是一场噩梦。

Next.js 基于 Turbopack 或 Webpack,依赖 Node.js 与 Edge 运行时;而 Expo 依赖 Metro 打包器与 React Native 的移动端 JS 引擎。最直觉的代码复用尝试往往以灾难告终:Metro 试图解析 Node 的 crypto 或 stream 原生模块报错,而 Turbopack 则被 React Native 特有的 JSX 语法阻塞。优雅解法的核心是严格的无头包封装。

设计无头共享包:认证、Schema 与类型契约

在生产级工程中,应用端(apps/web 与 apps/mobile)应该仅仅是薄薄的 UI 表现层。业务核心、数据库模型与认证配置应当归拢在 packages/ 目录下的内部包中:

@supastack/db:存放 Drizzle ORM 表结构定义、多表关联与迁移文件。仅服务端能引用数据库连接实例,客户端只引入推导出的 TypeScript 类型。

@supastack/auth:配置 Better Auth,并提供双入口点:供服务端路由使用的管理端点,以及供 Web 和移动端共同调用的无头 Client SDK。

@supastack/config:在编译阶段利用 Zod 对环境变量进行强类型校验,杜绝运行时的配置缺失崩溃。

// packages/auth/src/client.ts
import { createAuthClient } from "better-auth/react";
import { expoClient } from "@better-auth/expo/client";

export function createCrossPlatformAuthClient(baseURL: string, storage?: any) {
  return createAuthClient({
    baseURL,
    plugins: storage ? [expoClient({ scheme: "myapp", storage })] : [],
  });
}

统一跨端认证:Web 端 Cookie 与移动端 SecureStore

Web 端与移动端需要完全不同的会话持久化机制。在 Web 浏览器中,Next.js 下发 HTTP-only、SameSite=Lax 的安全 Cookie,自动获得 CSRF 防护与服务端组件无缝注水。

在原生手机端,Cookie 在各系统的 WebView 中极不可靠。Expo 应用通过 OAuth 或 Magic Link 交换获取安全的 Bearer 会话 Token,并借助 expo-secure-store 安全持久化到 iOS Keychain 或 Android Keystore 中。移动端出站请求携带 Authorization: Bearer <token> 请求头,由共享的 Better Auth 统一中间件校验。

CI/CD 与多端发布流水线:Vercel、EAS Build 与版本同步

在同一个代码仓库中维护 Web 与移动端,能带来版本协同更新的巨大红利。当 @supastack/db 中的数据库迁移合并后,Next.js 后端可在 Vercel 或 Cloud Run 上数秒内完成热部署。

与此同时,Expo Application Services(EAS Build)自动触发针对 Apple TestFlight 与 Google Play 内部测试轨道的原生打包。通过在 monorepo 内锁定共享依赖版本,你将彻底告别双仓库间版本脱节引发的幽灵故障。

下一个产品,从这里开始。

一次付费,持续打造盈利的产品。