仅在NextJS网站构建期间如何使用getInitialProps?

时间:2019-09-11 23:00:22

标签: javascript node.js next.js static-site

使用NextJS构建静态网站时,我希望getInitialProps方法仅在构建步骤中触发,而不在客户端上触发。

在构建步骤中,在使用每个组件的呈现HTML生成页面的静态HTML之前,NextJS运行getInitialProps method。在客户端上,NextJS还在呈现页面组件之前运行此方法,以便为该组件返回必要的道具。因此,大请求可能会延迟客户端的第一次绘画,因为这是一个阻塞请求。

// example usage of API call in getInitialProps
import fetch from 'isomorphic-unfetch'

function Page({ stars }) {
  return <div>Next stars: {stars}</div>
}

Page.getInitialProps = async ({ req }) => {
  const res = await fetch('https://api.github.com/repos/zeit/next.js')
  const json = await res.json()
  return { stars: json.stargazers_count }
}

export default Page

我不愿意将缓慢的API请求移至componentDidMount以避免阻塞请求,因为我想使用在构建步骤中返回的数据来填充静态HTML,而这个特定请求却没有。构建后不需要动态或更新。

有没有一种方法可以使getInitialProps生成时next export仅在客户端加载页面时运行

这是好习惯吗?

3 个答案:

答案 0 :(得分:7)

我发现了NextJs 9.0.3的解决方法(其他版本也可以使用,我没有测试过)

TimeTrigger2

答案 1 :(得分:1)

有两种方法是我发现的一种防止getInitialProps中的代码在页面组件加载时运行的方法。

1。在该页面上使用不带next/link的常规锚标记。

getInitialProps仅在从next/link组件链接页面时运行。如果改为使用常规JSX锚点<a href="/my-page">click me</a>,则将调用组件的getInitialProps。直接页面加载到NextJS静态站点页面将不会调用getInitialProps

请注意,使用标准锚代替next/link组件将导致整页刷新。

因为这是一个糟糕的解决方案,I've submitted a feature request


2。在req参数中使用contextgetInitialProps中有条件地进行API调用。

我相信@evgenifotia想要传达的是,req在导出的站点中未定义。

// example usage of API call in getInitialProps
import fetch from 'isomorphic-unfetch'

function Page({ stars }) {
  return <div>Next stars: {stars}</div>
}

Page.getInitialProps = async (ctx) => {
  const { req } = ctx // context object: { req, res, pathname, query, asPath }
  if (req) { // will only run during the build (next export)
    const res = await fetch('https://api.github.com/repos/zeit/next.js')
    const json = await res.json()
    return { stars: json.stargazers_count }
  }

  return {}
}

export default Page

有关getInitialProps的更多信息,请参见documentation。那里的一个示例确认了req仅应在服务器上定义(或在导出构建过程中):

const userAgent = req ? req.headers['user-agent'] : navigator.userAgent`

第二个选项可能在某些情况下有效,但是在从getInitialProps返回空结果会影响组件的this.props的情况下不是这样。


注意:

浅层路由不是答案。 According to the documentation(请参见“注释”部分):

  

浅路由仅适用于相同页面URL更改。

答案 2 :(得分:0)

截至接受的答案的更详细和更新的版本:

  const isInBroswer = typeof window !== 'undefined';
  if (isInBroswer) {
    const appCustomPropsString =
      document.getElementById('__NEXT_DATA__')?.innerHTML;

    if (!appCustomPropsString) {
      throw new Error(`__NEXT_DATA__ script was not found`);
    }

    const appCustomProps = JSON.parse(appCustomPropsString).props;
    return appCustomProps;
  }