如何从`getStaticProps`向API路由发出请求

Posted

技术标签:

【中文标题】如何从`getStaticProps`向API路由发出请求【英文标题】:How to make a request to an API route from `getStaticProps` [duplicate] 【发布时间】:2021-05-04 22:51:46 【问题描述】:

我想在网站上显示来自 YouTube 频道的最新视频。频道每天最多上传一次,所以我在vercel.json like so 中缓存了我的 API 路由响应 1 天(86400 秒):


    "headers": [
        
            "source": "/(.*)",
            "headers": [
                
                    "key": "access-control-allow-origin",
                    "value": "*"
                ,
                
                    "key": "Cache-Control",
                    "value": "s-maxage=86400"
                
            ]
        
    ]

我想使用getStaticProps with incremental static regeneration,这样我的 API 路由每天最多只能收到一次发送请求,但我不确定如何将请求写入我的 API 路由。

Next.js docs say:

注意:您不应使用fetch() 调用getStaticProps 中的API 路由。相反,直接导入 API 路由中使用的逻辑。您可能需要针对这种方法稍微重构您的代码。

从外部 API 获取很好!

这是什么意思?我现在写请求的方法有错吗?

// /pages/index.js

import Header from '../components/header/header'
import MainContent from '../components/main-content/main-content'
import Footer from '../components/footer/footer'

export default function Index( videoTitle, videoURL, videoThumbnailData ) 
    return (
        <>
            <Header />

            <MainContent
                videoTitle=videoTitle
                videoURL=videoURL
                videoThumbnailData=videoThumbnailData
            />

            <Footer />
        </>
    )


// Called at build time, and response revalidated after 1 day (86400 seconds)
// since internal API response is cached on Vercel Edge network for 1 day (see /pages/api/get-latest-video.js)
export async function getStaticProps() 
    // Fetch YouTube videos from internal API route /pages/api/get-latest-video.js
    const res = await fetch(`$process.env.API_ROUTES_URL/api/get-latest-video`)
    const data = await res.json()

    // Returned as props to page
    return 
        props: 
            videoTitle: data.videoTitle,
            videoURL: data.videoURL,
            videoThumbnailData: data.videoThumbnailData
        ,
        revalidate: 86400
    

// /components/main-content/main-content.js

import Section from './section'
import Image from 'next/image'

export default function MainContent( videoTitle, videoURL, videoThumbnailData ) 
    return (
        <main>
            <Section>
                <a href=videoURL>
                    videoTitle
                </a>
                <Image
                    src=videoThumbnailData.url
                    width=videoThumbnailData.width
                    height=videoThumbnailData.height
                />
            </Section>
        </main>
    )

【问题讨论】:

这意味着您应该直接将逻辑导入您的getStaticProps 函数,而不是调用您的内部 API 路由。检查这个答案***.com/questions/65752932/…,它提到了getServerSideProps,但原理是一样的。 【参考方案1】:

您的请求/api/get-latest-video 应该从浏览器发送到服务器,那么服务器可能有某种路由处理程序,例如:

routeMatches('/api/get-latest-video', ( req, res )=>
    requestDB('latestVideos').then( latestVideos => 
        respondWithLatestVideos( req, res, latestVideos );
    )
);

现在,getStaticProps 在服务器端运行。因此,您可以直接在 getStaticProps 中请求您的数据库,而不是向请求数据库的服务器发送请求。

export async function getStaticProps() 
    // Fetch YouTube videos from internal API route /pages/api/get-latest-video.js
    // const res = await fetch(`$process.env.API_ROUTES_URL/api/get-latest-video`)
    // const data = await res.json()
    const data = await requestDB('latestVideos')
    ...

在同一个 NextJs 文档页面的下方有一条信息更丰富的注释“write server side code directly”:

请注意,getStaticProps 仅在服务器端运行。它永远不会在客户端运行。它甚至不会包含在浏览器的 JS 包中。这意味着您可以编写诸如直接数据库查询之类的代码,而无需将它们发送到浏览器。您不应该从 getStaticProps 获取 API 路由 — 相反,您可以直接在 getStaticProps 中编写服务器端代码。

【讨论】:

【参考方案2】:

这意味着您只需将您的 api 函数导入 getStaticProps 而不是使用 Fetch

// /pages/index.js

import Header from "../components/header/header";
import MainContent from "../components/main-content/main-content";
import Footer from "../components/footer/footer";

export default function Index( videoTitle, videoURL, videoThumbnailData ) 
  return (
    <>
      <Header />

      <MainContent
        videoTitle=videoTitle
        videoURL=videoURL
        videoThumbnailData=videoThumbnailData
      />

      <Footer />
    </>
  );


// Called at build time, and response revalidated after 1 day (86400 seconds)
// since internal API response is cached on Vercel Edge network for 1 day (see /pages/api/get-latest-video.js)
export async function getStaticProps() 
  // Fetch YouTube videos from internal API route /pages/api/get-latest-video.js
  const res = await getApiData(); // import your api function here
  const data = await res.json();

  // Returned as props to page
  return 
    props: 
      videoTitle: data.videoTitle,
      videoURL: data.videoURL,
      videoThumbnailData: data.videoThumbnailData,
    ,
    revalidate: 86400,
  ;


【讨论】:

以上是关于如何从`getStaticProps`向API路由发出请求的主要内容,如果未能解决你的问题,请参考以下文章

是否可以使用 API 路由在 Next.JS getStaticProps/getStaticPaths 中构建页面? [复制]

如何从 getstaticprops 函数中的 Context API 获取数据?

如何在 getStaticProps 中获取 slug 值以调用 api,参数为 slug

NextJS:通过上下文将字符串从输入传递到 getStaticProps

使用 HOC 包装时,组件不会从 getStaticProps 接收道具

在 NextJS 中使用“getStaticPaths”和“getStaticProps”创建动态路由