首页 > 解决方案 > 使用 getServerSideProps 获取内部 API?(Next.js)

问题描述

我是 Next.js 的新手,我正在尝试了解建议的结构并处理页面或组件之间的数据。

例如,在我的页面home.js中,我获取了一个调用的内部 API /api/user.js,它从 MongoDB 中返回一些用户数据。我通过使用fetch()从内部调用 API 路由来做到这一点getServerSideProps(),它在一些计算后将各种道具传递到页面。

据我了解,这对 SEO 有好处,因为道具在服务器端被获取/修改,并且页面让它们准备好呈现。fetch()但后来我在Next.js文档中读到,你不应该使用getServerSideProps(). 那么我应该怎么做才能遵守良好的做法和良好的 SEO?

我没有home.js在 API 路由本身中进行所需计算的原因是我需要来自这个 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.

标签: javascriptnode.jsnext.jsserver-side-renderingfetch-api

解决方案


fetch()但后来我在Next.js文档中读到,你不应该使用getServerSideProps().

您想直接使用 API 路由中的逻辑getServerSideProps,而不是调用内部 API。那是因为getServerSideProps就像 API 路由一样在服务器上运行(从服务器向服务器本身发出请求是没有意义的)。您可以从文件系统读取或直接从getServerSideProps.

来自 Next.jsgetServerSideProps文档:

当您想从服务器获取数据时,可能很容易使用 API 路由,然后从 getServerSideProps. 这是一种不必要且低效的方法,因为它会由于 getServerSideProps服务器上运行的 API 路由和 API 路由而导致发出额外的请求。

(...) 相反,直接将 API Route 中使用的逻辑导入getServerSideProps. 这可能意味着直接从内部调用 CMS、数据库或其他 API getServerSideProps

(请注意,使用getStaticProps/getStaticPaths方法时同样适用)


这是一个小的重构示例,它允许您在getServerSideProps.

假设您有这个简单的 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)
}

而且还允许你重复getData使用getServerSideProps.

// pages/home
import { getData } from './api/user'

//...

export async function getServerSideProps(context) {
    const jsonData = await getData()
    //...
}

推荐阅读