如何仅在 NextJS 站点构建期间使用 getInitialProps?
How can I use getInitialProps only during the NextJS site build?
当使用 NextJS 构建静态站点时,我希望 getInitialProps
方法仅在构建步骤期间触发,而不是在客户端触发。
在构建步骤中,NextJS 运行在每个组件呈现HTML之前的getInitialProps method用于生成页面的静态HTML。在客户端,NextJS 还在页面组件呈现之前 运行s 这个方法,以便 return 组件的必要道具。因此,大请求可能会延迟客户端的第一次绘制,因为这是一个阻塞请求。
// 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
以避免阻塞请求,因为我想在构建步骤中使用数据 returned 来填充静态 HTML,并且此特定请求不需要是动态的或在构建后更新。
有什么方法可以让 getInitialProps
运行 只有 当 next export
构建时 没有 当客户端加载页面时?
这是好的做法吗?
对于版本 9.3 或更高版本,it's recommended that you use getStaticProps
用于提供静态构建道具。
export async function getStaticProps(context) {
return {
props: {}, // will be passed to the page component as props
}
}
旧答案
有两种方法 是我发现的一种方法,可以防止 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。在 context
参数中使用 req
以有条件地在 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(见“注释”部分):
Shallow routing works only for same page URL changes.
我找到了 NextJs 9.0.3 的解决方法(其他版本也可能有效,我没有测试)
// XXXPage is your page
XXXPage.getInitialProps = async (req) => {
if (process.browser) {
return __NEXT_DATA__.props.pageProps;
}
// original logic
}
已接受答案的更详细和更新版本:
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;
}
当使用 NextJS 构建静态站点时,我希望 getInitialProps
方法仅在构建步骤期间触发,而不是在客户端触发。
在构建步骤中,NextJS 运行在每个组件呈现HTML之前的getInitialProps method用于生成页面的静态HTML。在客户端,NextJS 还在页面组件呈现之前 运行s 这个方法,以便 return 组件的必要道具。因此,大请求可能会延迟客户端的第一次绘制,因为这是一个阻塞请求。
// 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
以避免阻塞请求,因为我想在构建步骤中使用数据 returned 来填充静态 HTML,并且此特定请求不需要是动态的或在构建后更新。
有什么方法可以让 getInitialProps
运行 只有 当 next export
构建时 没有 当客户端加载页面时?
这是好的做法吗?
对于版本 9.3 或更高版本,it's recommended that you use getStaticProps
用于提供静态构建道具。
export async function getStaticProps(context) {
return {
props: {}, // will be passed to the page component as props
}
}
旧答案
有两种方法 是我发现的一种方法,可以防止 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。在 context
参数中使用 req
以有条件地在 getInitialProps
.
中调用 API
context
参数中使用 req
以有条件地在 getInitialProps
.我相信@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(见“注释”部分):
Shallow routing works only for same page URL changes.
我找到了 NextJs 9.0.3 的解决方法(其他版本也可能有效,我没有测试)
// XXXPage is your page
XXXPage.getInitialProps = async (req) => {
if (process.browser) {
return __NEXT_DATA__.props.pageProps;
}
// original logic
}
已接受答案的更详细和更新版本:
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;
}