You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Server Components中优化Fetch请求?最佳实践探讨

Next.js Server Components 中 Fetch 请求的最佳实践

针对你遇到的Server Components中Fetch请求重复代码问题,业内通用的最佳实践是通过封装统一请求工具+模块化API分层来解决,具体实现如下:

1. 封装通用请求工具函数

把baseURL拼接、授权头注入、错误处理这些重复逻辑抽成一个通用函数,比如在/app/utils/api-fetch.ts中:

import { cookies } from 'next/headers';

type ApiFetchOptions = Omit<RequestInit, 'headers'> & {
  headers?: Record<string, string>;
};

export async function apiFetch<T = unknown>(
  endpoint: string,
  options: ApiFetchOptions = {}
): Promise<T> {
  // 获取授权Token
  const cookieStore = cookies();
  const accessToken = cookieStore.get('accessToken')?.value;

  // 拼接完整API地址
  const baseUrl = process.env.NEXT_PUBLIC_API_BASE_URL;
  const url = `${baseUrl}${endpoint}`;

  // 合并请求头,优先传入的headers,默认添加授权头
  const headers = {
    'X-Authorization': accessToken ? `Bearer ${accessToken}` : '',
    'Content-Type': 'application/json',
    ...options.headers,
  };

  const res = await fetch(url, {
    ...options,
    headers,
    // 可选:全局默认缓存策略,业务请求可覆盖
    next: { revalidate: 60 },
  });

  // 统一错误处理,返回更具体的错误信息
  if (!res.ok) {
    const errorData = await res.json().catch(() => null);
    throw new Error(errorData?.message || `Request failed with status ${res.status}`);
  }

  return res.json() as Promise<T>;
}

2. 模块化API请求层

将每个业务的API请求单独封装,放在统一的/app/api目录下,便于维护和复用:

/app/api/suite.ts:

import { apiFetch } from '@/app/utils/api-fetch';
import { Suite } from '@/types';

export async function getSuite(propertyId: string, suiteId: string): Promise<Suite> {
  // 可根据业务需求覆盖缓存策略或请求头
  return apiFetch<Suite>(`/suite?propertyId=${propertyId}&suiteId=${suiteId}`);
}

/app/api/sensors.ts:

import { apiFetch } from '@/app/utils/api-fetch';
import { Sensor } from '@/types';

export async function getSensorData(deviceId: string): Promise<Sensor[]> {
  return apiFetch<Sensor[]>(`/sensors?deviceId=${deviceId}`);
}

3. Server Components中使用

在Server Components里直接调用封装好的API函数,用Promise.all并行请求提升性能:

import { getSuite } from '@/app/api/suite';
import { getSensorData } from '@/app/api/sensors';

async function ServerComponent() {
  // 并行请求,避免串行等待
  const [suite, sensors] = await Promise.all([
    getSuite('property-123', 'suite-456'),
    getSensorData('device-789'),
  ]);

  return (
    <div>
      <h2>Suite: {suite.name}</h2>
      <div>Sensors count: {sensors.length}</div>
    </div>
  );
}

export default ServerComponent;

额外优化点

  • 类型安全:为API请求定义返回类型,结合TypeScript确保前后端类型一致性
  • 缓存定制:业务API函数可通过apiFetch的next参数覆盖全局缓存策略,比如apiFetch('/suite', { next: { revalidate: 30 } })
  • 错误处理:在Server Components中用try/catch捕获请求错误,返回友好的错误UI
  • POST请求支持:可在apiFetch中统一处理body序列化,自动将对象转为JSON字符串

内容的提问来源于stack exchange,提问作者ERTY

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 15:43:11