提问人:grazdev 提问时间:7/23/2023 更新时间:7/23/2023 访问量:355
如何在 Nextjs 13 中编写一个在服务器和客户端上都能工作的提取器?
How to write a fetcher that works both on the server and the client in Nextjs 13?
问:
我有一个 Nextjs 13 前端(应用程序路由器),它通过 api 与 Laravel 支持的后端进行通信。对于 api 中的身份验证,我使用 Laravel Sanctum(正如 Laravel 为 SPA 推荐的那样):基本上,身份验证的工作原理是在登录后设置两个 cookie(一个会话和一个 CSRF 令牌),然后应该将其附加到所有未来的请求,以及传递 CSRF 令牌的标头。X-Xsrf-Token
要从客户端组件发送请求,我可以执行以下操作:
import cookies from 'js-cookie'
fetch( [url], {
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
"Origin": [origin],
"X-Requested-With": "XMLHttpRequest",
"X-Xsrf-Token": cookies.get( "XSRF-TOKEN" ),
// Since we're on the browser, cookies are automatically attached via the 'Cookie' header
},
credentials: 'include'
})
如果我从服务器组件发送请求,我可以执行以下操作:
import { cookies, headers } from "next/headers"
fetch( [url], {
headers: {
"Cookie": cookies().toString(), // Must attach cookies manually
"Referer": headers().get( "referer" ) ?? "",
"X-Xsrf-Token": cookies().get( "XSRF-TOKEN" ).value,
},
})
两个提取器都可以工作。但是,有时我需要从服务器组件和客户端组件发出相同的请求,因此我想使用这样的单个获取器(这是一个快速而肮脏的示例,只是为了表达我的观点):
import cookies from 'js-cookie'
import { cookies, headers } from "next/headers"
fetch( [url],
isServer
?
{
headers: {
"Cookie": cookies().toString(), // Must attach cookies manually
"Referer": headers().get( "referer" ) ?? "",
"X-Xsrf-Token": cookies().get( "XSRF-TOKEN" ).value,
}
}
:
{
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" ),
// Since we're on the browser, cookies are automatically attached via the 'Cookie' header
},
credentials: 'include'
}
)
但这会在客户端组件中引发错误,因为 and 函数只能在服务器组件中使用。cookies()
headers()
那么,简而言之,我怎样才能编写一个同时适用于服务器和客户端组件的提取器呢?
答:
没错,不能在客户端组件中使用 cookies() 和 headers() 函数,因为它们是服务器函数。这些函数旨在用于服务器组件或服务器操作。
但是,您可以创建一个实用程序函数来检查代码是在服务器还是客户端上运行,然后相应地执行提取。下面是一个基本示例:
import cookies from 'js-cookie'
import { cookies as serverCookies, headers } from "next/headers"
function isServer() {
return typeof window === 'undefined';
}
async function universalFetch(url, options = {}) {
if (isServer()) {
options.headers = {
...options.headers,
"Cookie": serverCookies().toString(),
"Referer": headers().get("referer") ?? "",
"X-Xsrf-Token": serverCookies().get("XSRF-TOKEN").value,
};
} else {
options.headers = {
...options.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"),
};
options.credentials = 'include';
}
return fetch(url, options);
}
此 universalFetch 函数首先使用 isServer 函数检查它是在服务器还是客户端上运行。如果它位于服务器上,则使用 next/headers 中的 serverCookies 和 headers 函数来设置标头。如果它位于客户端上,则它使用 js-cookie 中的 cookies 函数来获取 XSRF-TOKEN,并将凭据选项设置为“include”。
评论