当前位置: 首页 > news >正文

Next.js + TanStack Query 架构中三种常见的数据请求模式

这三种模式各有优劣,适用于不同的场景。


模式一:BFF 代理模式 (Frontend -> Next.js API Route -> Backend)

这种模式的完整流程是:
前端页面组件 -> useXXX (自定义 Hook) -> xxxService -> fetch('/api/backend') -> Next.js API Route -> proxyBackendUtils.request -> 真正的后端服务

这是一个典型的 BFF (Backend for Frontend) 模式。Next.js 的 API Route 充当了前端和后端之间的代理层和适配层。

优点 (Pros):
  1. 安全性高: 这是最大的优点。后端的真实地址、API Keys、Secrets、数据库连接字符串等敏感信息永远不会暴露在浏览器端。所有认证和鉴权逻辑都可以在这个安全的服务器环境(Next.js API Route)中处理。
  2. 解决CORS问题: 浏览器请求的是同源的 /api/backend,完全没有跨域问题。Next.js 服务器与后端服务之间的通信是服务器到服务器的,不受浏览器同源策略的限制。
  3. 数据聚合与裁剪: 可以在 API Route 中调用多个后端服务,将数据聚合成一个前端需要的格式,或者剔除掉前端不需要的敏感字段。这大大简化了前端的逻辑。
  4. 协议转换: 如果后端服务使用的是 gRPC、GraphQL 等不同协议,BFF 层可以将其转换为前端易于消费的 RESTful API。
缺点 (Cons):
  1. 增加了一次网络跳跃: 请求链路变长了(浏览器 -> Next.js 服务器 -> 后端服务器),理论上会增加一点点延迟。但在内网环境(如 Vercel Serverless Function 与后端服务在同一云服务商的同一区域),这个延迟通常可以忽略不计。
  2. 增加了维护成本: 你需要编写和维护这层 API Route 代理逻辑。
适用场景:

这是绝大多数生产级应用推荐的模式,尤其是当需要处理认证、隐藏敏感信息、或者前端需要的数据格式与后端直接提供的不一致时。


模式二:前端直连后端模式 (CSR - Client-Side Rendering)

这种模式的完整流程是:
前端页面组件 -> useXXX -> xxxService -> fetch('https://api.my-real-backend.com/data')

这是最经典的客户端渲染(CSR)数据请求方式。

优点 (Pros):
  1. 简单直接: 架构最简单,不需要额外的 BFF 层。
  2. 延迟较低: 少了一次网络中转,请求直达后端服务。
缺点 (Cons):
  1. 安全性差: 后端服务的地址直接暴露在前端代码中。如果需要 API Key,也只能使用那些可以安全暴露在前端的 “Public Key”。
  2. CORS 配置复杂: 后端服务必须正确配置 CORS (Cross-Origin Resource Sharing),允许来自你前端应用的域名请求。
  3. 前端逻辑复杂: 如果需要聚合多个 API 的数据,这些逻辑都必须在前端完成,增加了前端的复杂度和请求数量。
适用场景:
  • 后端是公开的、无需鉴权的 API (例如,天气 API、公共数据查询)。
  • 后端服务已经为你这个前端应用做好了完善的 CORS 和安全配置。
  • 项目非常简单,不需要 BFF 带来的那些好处。

模式三:Next.js 服务端预取数据 (SSR/SSG)

这种模式的完整流程是:

  1. 服务端 (Server-Side): getServerSidePropsgetStaticProps (或 App Router 中的 Server Component) -> queryClient.prefetchQuery(xXXOptions()) -> queryFn -> xxxService -> 直接请求 APP_BACKEND_URL
  2. 数据传递 (Hydration): 服务端将预取的数据序列化后注入到页面 HTML 中。
  3. 客户端 (Client-Side): 页面在浏览器加载后,useQuery(xXXOptions()) 会立即从已经存在于缓存中的数据(通过 Hydration 获得)中读取,用户不会看到 Loading 状态。

这是一个利用 Next.js 服务端能力结合 TanStack Query 实现高性能初始加载的模式。

优点 (Pros):
  1. 极致的首屏性能 (LCP): 用户打开页面时,数据已经存在,页面内容立即可见,没有加载中的闪烁。
  2. 利于 SEO: 搜索引擎爬虫可以直接抓取到包含完整内容的 HTML。
  3. 高效的数据获取: 在服务端发起请求,通常是服务器到服务器的内网通信,速度远快于客户端通过公网的请求。
  4. 安全性: 和模式一一样,敏感信息和后端真实地址都保留在服务端。
缺点 (Cons):
  1. TTFB (Time To First Byte) 变长: 服务器必须等待数据获取完成后才能响应 HTML,如果后端 API 慢,会导致白屏时间变长。
  2. 增加了服务端负载: 数据请求的压力转移到了 Next.js 服务器上。
  3. 实现稍复杂: 需要理解 prefetchQuerydehydratehydrate 的概念。
适用场景:
  • 对 SEO 和首屏性能要求极高的页面,如文章详情页、商品详情页、首页。
  • 页面核心内容依赖于异步数据。

总结与最佳实践

这三种模式并不互斥,在一个复杂的应用中,它们往往会组合使用。

特性模式一 (BFF)模式二 (直连)模式三 (SSR/SSG 预取)
安全性
首屏性能正常 (有 Loading)正常 (有 Loading)极佳
SEO极佳
实现复杂度
CORS处理无需关心必须处理无需关心
典型场景绝大多数客户端后续交互公共API、简单应用核心内容、落地页
关键点:xXXOptions() 的重用

你提到的 xXXOptions() 是一个非常关键且优秀的实践。它将 queryKeyqueryFn 封装在一起。

// a file like: src/queries/xxxQueries.ts// 定义查询选项,这个函数可以在任何地方被导入和使用
export const xxxOptions = (params) => ({queryKey: ['xxx', params],queryFn: () => xxxService.get(params),
});// 在客户端组件中使用
function MyComponent() {const { data } = useQuery(xxxOptions(params));// ...
}// 在服务端预取时使用
export async function getServerSideProps(context) {const queryClient = new QueryClient();await queryClient.prefetchQuery(xxxOptions(params));return {props: {dehydratedState: dehydrate(queryClient),},};
}

为什么这很重要?
因为 TanStack Query 的 Hydration 机制依赖于 完全相同的 queryKey。通过重用 xxxOptions(),你可以确保在服务端 prefetchQuery 和在客户端 useQuery 时使用的 queryKey 绝对一致,从而让数据成功地从服务端“水合”到客户端缓存中。

推荐的混合架构 (The “Best of Both Worlds” Approach)

一个强大的现代 Next.js 应用通常会结合 模式一模式三

  1. 首次加载 (Initial Load):

    • 使用 getServerSideProps (或 Server Component) 执行 模式三 的逻辑。
    • queryFn 中,xxxService 直接通过内网地址 (APP_BACKEND_URL) 请求后端数据,实现快速、安全的数据预取。
    • 页面实现极速加载和 SEO 优化。
  2. 客户端交互 (Client-Side Interactions):

    • 当用户在页面上进行操作(如翻页、筛选、点击刷新)时,useQuery 会触发 refetch,或者 useMutation 被调用。
    • 此时,xxxService 中发起的请求应该走 模式一 的 BFF 代理 (/api/backend)。
    • 这样做可以保持客户端交互的安全性,并且 useQuery 的所有强大功能(缓存、后台自动刷新、重试等)都能正常工作。

这种组合拳,既利用了 Next.js 的服务端渲染能力来优化首屏,又利用了 BFF 模式来保障后续客户端交互的安全性,同时通过 TanStack Query 统一了数据状态管理,是目前非常先进和稳健的架构选择。

http://www.dtcms.com/a/406987.html

相关文章:

  • ISO 雨晨 26200.6588 Windows 11 企业版 LTSC 25H2 自用 edge 140.0.3485.81
  • 企业手机app开发公司网站优化策划方案
  • 建网站的免费空间百度检索入口
  • 厦门品牌网站建设丽水市住房和城乡建设局网站
  • EsModule和Common.js区别
  • [Vue warn]: Error in mounted hook: “ReferenceError: Jessibuca is not defined“
  • Linux 修炼:进程控制(一)
  • 如何把代码放在网站首页教程门户网站开发如何提高产品排名
  • 建设网站公司招聘做非法网站要多少钱
  • 网站标题权重云建站不能用了吗
  • Python快速入门专业版(四十六):Python类的方法:实例方法、类方法、静态方法与魔术方法
  • 嵌入式 - 内核驱动2 - 实现设备驱动
  • 做机械设计的网站长沙网站推广
  • 景泰做网站wordpress资源分享
  • Vue 3 中的事件总线
  • OCR 如何精准识别越南身份证?
  • FPGA自学笔记--VIVADO FIFO IP核控制和使用
  • 张家界官方网站查询网ip138子域名
  • 【通信】无线PA 释义
  • 襄阳做公司网站的软件公司建立个人网站能赚钱吗
  • 赛迪顾问《2025中国虚拟化市场研究报告》解读丨虚拟化市场迈向“多元算力架构”,国产化与AI驱动成关键变量
  • 汕头公众号建设网站北京模板开发建站
  • 【Linux】UDP 网络编程
  • Redis 键空间 五大类型
  • seata部署与集成
  • ORM框架Java持久化层使用手册(mybatis,mybatisplus,jpa等)
  • 大型企业网站建设方案seo排名优化软件有用
  • 数据驱动下的高维数据破局术:降维处理的技术实战、选型指南与方法论沉淀
  • Java按顺序提取Word内容(文本+数学公式)
  • Python快速入门专业版(四十五):Python类的属性:实例属性、类属性与属性访问控制(封装特性)