如何编写Next.js 13服务端与客户端通用的请求工具?
实现Next.js 13 App Router与Laravel Sanctum的通用请求工具
要解决服务端专属API在客户端组件报错的问题,核心思路是环境隔离+动态导入,避免在客户端执行服务端代码。以下是具体实现方案:
1. 封装通用请求函数
创建工具文件(如utils/api-fetch.ts),通过环境判断分支处理服务端/客户端的请求配置,同时动态导入服务端专属模块:
import type { RequestInit } from 'node-fetch'; import Cookies from 'js-cookie'; // 扩展请求配置类型,允许自定义headers type ApiFetchOptions = Omit<RequestInit, 'headers'> & { headers?: Record<string, string>; }; export async function apiFetch(url: string, options: ApiFetchOptions = {}) { const isServer = typeof window === 'undefined'; const fetchOptions: RequestInit = { ...options }; if (isServer) { // 服务端环境:动态导入Next.js服务端API,避免客户端加载 const { cookies, headers } = await import('next/headers'); const cookieStore = cookies(); const requestHeaders = headers(); fetchOptions.headers = { ...fetchOptions.headers, 'Cookie': cookieStore.toString(), 'Referer': requestHeaders.get('referer') ?? '', 'X-Xsrf-Token': cookieStore.get('XSRF-TOKEN')?.value || '', }; } else { // 客户端环境:使用浏览器Cookie和标准请求头 fetchOptions.headers = { ...fetchOptions.headers, 'Accept': 'application/json', 'Content-Type': 'application/json', 'Origin': process.env.NEXT_PUBLIC_APP_URL || '', 'X-Requested-With': 'XMLHttpRequest', 'X-Xsrf-Token': Cookies.get('XSRF-TOKEN') || '', }; fetchOptions.credentials = 'include'; } return fetch(url, fetchOptions); }
2. 在组件中使用
客户端组件('use client')
'use client'; import { apiFetch } from '@/utils/api-fetch'; async function UserProfile() { const response = await apiFetch('/api/auth/user'); const user = await response.json(); return <div>当前用户:{user.name}</div>; } export default UserProfile;
服务端组件
import { apiFetch } from '@/utils/api-fetch'; async function Dashboard() { const response = await apiFetch('/api/dashboard/stats'); const stats = await response.json(); return <div>今日访问量:{stats.today_visits}</div>; } export default Dashboard;
3. 关键注意点
- 环境判断:用
typeof window === 'undefined'区分服务端/客户端,这是Next.js中安全可靠的判断方式。 - 动态导入:服务端环境下动态导入
next/headers,确保客户端组件不会加载该模块,避免调用服务端专属函数报错。 - Cookie处理:客户端依赖浏览器自动携带Cookie(通过
credentials: 'include'),服务端则手动拼接Cookie字符串。 - 配置兼容性:确保Laravel Sanctum的
SANCTUM_STATEFUL_DOMAINS环境变量包含你的Next.js域名,否则认证会失效。 - 灵活性:函数支持传入自定义headers和请求配置,满足不同场景的需求。
内容的提问来源于stack exchange,提问作者grazdev
相关产品推荐
相关产品推荐

