使用 Next.js 构建大规模 SaaS 的集中式 Action

发布: (2025年12月4日 GMT+8 16:49)
5 min read
原文: Dev.to

Source: Dev.to

架构概览

在大型 SaaS 项目中,若在每个模块中单独处理服务器动作会导致代码重复。
集中式变更引擎 将所有 API 变更统一到一个可复用的函数中。它负责身份验证、授权、店铺/子域名上下文、请求负载、fetch 执行以及缓存重新验证。

核心工具

  • logger – 用于调试和监控的结构化日志。
  • resolveModelName – 将路由名称如 saved-attribute 转换为 saved_attribute
  • hasPermissionparseAccessRules – 实现 RBAC,检查用户是否可以执行特定操作。
  • getBaseUrlWithSubdomain – 根据店铺子域名解析正确的 API 基础 URL。

身份验证处理

if (requireAuth) {
  const accessToken = cookieStore.get("accessToken")?.value;
  if (!accessToken) {
    return { message: "You are not authorized to perform this action!" };
  }
  // Validate JWT access token...
}

店铺 / 子域名上下文

if (requireShopId) {
  const subdomain = cookieStore.get("shopSubdomain")?.value;
  if (!subdomain) {
    return { message: "Shop identifier not found!" };
  }
  // Use subdomain for multi‑tenant routing...
}

基于角色的访问控制 (RBAC)

const rulesRaw = cookieStore.get("accessRules")?.value;
const rules = parseAccessRules(rulesRaw);
const model = resolveModelName(route.split("/")[1]);
const action = methodToAction[method];

if (!hasPermission(rules, model, action)) {
  return { success: false, message: "Permission denied" };
}

将 HTTP 方法映射为 CRUD 操作。

动态负载处理

let body: string | undefined = undefined;

if (method === "DELETE" && ids?.length) {
  body = JSON.stringify({ ids });
} else if (method !== "DELETE" && data) {
  body = data;
}

支持单 ID 删除、批量删除以及 POST/PUT 负载。

Fetch 执行

const response = await fetch(url, {
  method,
  headers,
  body,
  cache: "no-store",
});
const result = await response.json();

使用 no-store 选项执行服务器端变更,确保获取最新数据。

缓存重新验证

paths.forEach(path => typeof path === "string" && revalidatePath(path));
tags.forEach(tag => typeof tag === "string" && revalidateTag(tag));

在变更后自动重新验证 Next.js 路径或标签。

错误处理与日志记录

try {
  // ...mutation logic...
} catch (error) {
  logger(error);
  return { success: false, message: "An error occurred during the mutation." };
}

统一错误处理。

好处

  • 可复用性 – 所有模型共用单一变更处理器。
  • 安全性 – 全局 RBAC 强制执行。
  • 多租户就绪 – 处理店铺特定子域名。
  • 一致性 – 统一日志、错误处理和缓存重新验证。
  • 可扩展性 – 随 SaaS 规模增长易于扩展。

使用示例

await mutation({
  route: "/customer",
  method: "POST",
  data: JSON.stringify({ name: "John Doe" }),
  pathToRevalidate: "/customers",
  tagsToRevalidate: ["customer‑list"],
});

一次调用即可处理身份验证、RBAC、负载以及缓存失效。

流程图

┌────────────────────┐
│  Client / Frontend │
│ (React / Next.js)  │
└─────────┬──────────┘


┌────────────────────┐
│  Server Action Call│
│   mutation(params) │
└─────────┬──────────┘

 ┌────────┴─────────┐
 │                  │
 ▼                  ▼
┌───────────────┐ ┌───────────────┐
│ AUTHENTICATION│ │ SHOP / SUBDOMAIN│
│ check JWT token│ │ get shop identifier│
│ from cookies   │ │ from cookies      │
└───────┬───────┘ └───────┬───────┘
        │                 │
        └───────┬─────────┘

        ┌─────────────────────┐
        │ ROLE‑BASED ACCESS   │
        │ CONTROL (RBAC)      │
        │ hasPermission()     │
        │ parseAccessRules()  │
        └───────┬─────────────┘

        ┌─────────────────────┐
        │ Construct Headers   │
        │ - Authorization     │
        │ - x‑app‑identifier   │
        └───────┬─────────────┘

        ┌─────────────────────┐
        │ Determine Payload   │
        │ - DELETE ids array  │
        │ - POST / PUT data   │
        └───────┬─────────────┘

        ┌─────────────────────┐
        │ FETCH Request       │
        │ method, headers,    │
        │ body                │
        └───────┬─────────────┘

        ┌─────────────────────┐
        │ Response Handling   │
        │ - parse JSON        │
        │ - log errors        │
        └───────┬─────────────┘

   ┌───────────────┬───────────────┐
   ▼               ▼               ▼
┌───────┐     ┌───────┐        ┌───────┐
│ PATH  │     │ TAG   │        │ CLIENT│
│ REVAL │     │ REVAL │        │ UI    │
└───────┘     └───────┘        └───────┘

要点

  • 集中式服务器动作减少样板代码并提升可维护性。
  • RBAC 确保所有 API 变更拥有一致的安全性。
  • 支持子域名感知的多租户架构,满足 SaaS 可扩展性需求。
  • 自动缓存重新验证保证 UI 始终展示最新数据。

在大型 SaaS 项目中实现集中式变更引擎,可显著提升代码可维护性、安全性和可扩展性。通过将身份验证、RBAC、多租户子域名处理、负载管理以及缓存重新验证统一到单一服务器动作,开发者能够:

  • 消除多个端点之间的重复代码。
  • 通过动态权限检查强制统一的安全策略。
  • 通过子域名感知的 API 调用高效支持多租户架构。
  • 通过自动重新验证 Next.js 路径和标签确保 UI 一致性。
  • 随着 SaaS 的增长轻松扩展,添加新模型和操作时几乎没有摩擦。
Back to Blog

相关文章

阅读更多 »

面向平台的 Vercel 介绍

您现在可以使用今天宣布的新产品构建平台,使您能够轻松代表用户创建和运行客户项目。Vercel for Platform…