使用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
仅在客户端加载页面时运行 而不?
这是好习惯吗?
答案 0 :(得分:7)
我发现了NextJs 9.0.3的解决方法(其他版本也可以使用,我没有测试过)
TimeTrigger2
答案 1 :(得分:1)
有两种方法是我发现的一种防止getInitialProps
中的代码在页面组件加载时运行的方法。
next/link
的常规锚标记。 getInitialProps
仅在从next/link
组件链接页面时运行。如果改为使用常规JSX锚点<a href="/my-page">click me</a>
,则将不调用组件的getInitialProps
。直接页面加载到NextJS静态站点页面将不会调用getInitialProps
。
请注意,使用标准锚代替next/link
组件将导致整页刷新。
因为这是一个糟糕的解决方案,I've submitted a feature request。
req
参数中使用context
在getInitialProps
中有条件地进行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;
}