【问题标题】:How to make a request to an API route from `getStaticProps` [duplicate]如何从`getStaticProps`向API路由发出请求
【发布时间】: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 路由。检查这个答案stackoverflow.com/questions/65752932/…,它提到了getServerSideProps,但原理是一样的。

标签: javascript reactjs api next.js vercel


【解决方案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,
      };
    }
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-18
      • 2019-08-13
      • 2019-11-11
      相关资源
      最近更新 更多