使用 getServerSideProps 获取内部 API? (Next.js)
Posted
技术标签:
【中文标题】使用 getServerSideProps 获取内部 API? (Next.js)【英文标题】:Internal API fetch with getServerSideProps? (Next.js) 【发布时间】:2021-04-21 11:26:01 【问题描述】:我是 Next.js 的新手,我正在尝试了解建议的结构并处理页面或组件之间的数据。
例如,在我的页面home.js
中,我获取了一个名为/api/user.js
的内部API,它从MongoDB 返回一些用户数据。我这样做是通过使用fetch()
从getServerSideProps()
中调用API 路由来实现的,该路由经过一些计算后将各种道具传递给页面。
据我了解,这有利于 SEO,因为道具会在服务器端获取/修改,并且页面可以让它们准备好呈现。但后来我在 Next.js 文档中读到,您不应该将 fetch()
用于 getServerSideProps()
中的所有 API 路由。那么我应该怎么做才能遵守良好的做法和良好的 SEO?
我没有在 API 路由本身中对 home.js
进行所需计算的原因是我需要来自此 API 路由的更多通用数据,因为我也会在其他页面中使用它。
我还必须考虑缓存,哪个客户端使用 SWR 来获取内部 API 非常简单,但服务器端我还不确定如何实现它。
home.js
:
export default function Page( prop1, prop2, prop3 )
// render etc.
export async function getServerSideProps(context)
const session = await getSession(context)
let data = null
var aArray = [], bArray = [], cArray = []
const db = await connectToDatabase()
function shuffle(array)
var currentIndex = array.length, temporaryValue, randomIndex;
while (0 !== currentIndex)
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
return array;
if (session)
const hostname = process.env.NEXT_PUBLIC_SITE_URL
const options = headers: cookie: context.req.headers.cookie
const res = await fetch(`$hostname/api/user`, options)
const json = await res.json()
if (json.data) data = json.data
// do some math with data ...
// connect to MongoDB and do some comparisons, etc.
【问题讨论】:
【参考方案1】:但后来我在 Next.js 文档中读到,您不应该将
fetch()
用于getServerSideProps()
中的所有 API 路由。
您希望直接在 getServerSideProps
中使用 API 路由中的逻辑,而不是调用您的内部 API。那是因为getServerSideProps
就像 API 路由一样在服务器上运行(从服务器向服务器本身发出请求是没有意义的)。您可以从文件系统读取或直接从getServerSideProps
访问数据库。
(注意the same applies when using getStaticProps
/getStaticPaths
methods)
这是一个小的重构示例,它允许您在 getServerSideProps
中重用来自 API 路由的逻辑。
假设您有这个简单的 API 路由。
// pages/api/user
export default async function handler(req, res)
// Using a fetch here but could be any async operation to an external source
const response = await fetch(/* external API endpoint */)
const jsonData = await response.json()
res.status(200).json(jsonData)
您可以将获取逻辑提取到一个单独的函数中(如果需要,仍然可以将其保存在api/user
),它仍然可以在 API 路由中使用。
// pages/api/user
export async function getData()
const response = await fetch(/* external API endpoint */)
const jsonData = await response.json()
return jsonData
export default async function handler(req, res)
const jsonData = await getData()
res.status(200).json(jsonData)
而且还允许您在getServerSideProps
中重复使用getData
函数。
// pages/home
import getData from './api/user'
//...
export async function getServerSideProps(context)
const jsonData = await getData()
//...
【讨论】:
导出功能是我在其他地方也需要的,我需要一个可重用的功能,但没有人建议我以这种方式导出它,谢谢,我会试试这个 绝对,在某些情况下我解决它的另一种方法是使用“useSWR”客户端,它也会自动缓存请求。 太棒了!沮丧了一整天发现这终于可以立即在框中获取数据了!为什么 api/routes 不直接为什么需要以其他方式提供它,他们采取了什么样的方法来建立,我不明白!一切都是为了在我们的头上绕圈子!抱歉,这可能是我令人沮丧的评论! 这很奇怪,从其他优秀的文档中看不清楚【参考方案2】:尝试使用useSWR
,示例如下
import useSWR from 'swr'
import React from 'react';
//important to return only result, not Promise
const fetcher = (url) => fetch(url).then((res) => res.json());
const Categories = () =>
//getting data and error
const data, error = useSWR('/api/category/getCategories', fetcher)
if (error) return <div>Failed to load</div>
if (!data) return <div>Loading...</div>
if (data)
// data is completed, it's ok!
//your code here to make something with data
return (
<div>
//something here, example data.name
</div>
)
export default Categories
请注意,fetch
仅限 supports absolute URLs,这就是我不喜欢使用它的原因。
附:根据docs,您甚至可以将useSWR
与s-s-r
一起使用。
【讨论】:
我只是使用环境变量来完成绝对路径。以上是关于使用 getServerSideProps 获取内部 API? (Next.js)的主要内容,如果未能解决你的问题,请参考以下文章
getServerSideProps 与直接在 React 中获取
Nextjs Auth0 在 getServerSideProps 中获取数据
在 NextJs 中如何使用更改事件更改 getServerSideProps
如何在 getServerSideProps 之外获取 cookie?
在 NEXTJS 的 getServerSideProps() 中获取一些 html 表单数据(或对象)
NextJS + Apollo:如何在 getServerSideProps 内的 apolloClient.query 上获取多个查询?