Nextjs getInitialProps 阻止了客户端的页面渲染?
Posted
技术标签:
【中文标题】Nextjs getInitialProps 阻止了客户端的页面渲染?【英文标题】:Nextjs getInitialProps blocked the page rendering in client side? 【发布时间】:2020-06-27 17:12:57 【问题描述】:由于我想将 s-s-r 添加到我即将进行的项目中以改进 SEO,因此我想尝试下一个。我想要的是只对初始页面使用 s-s-r,站点中的其余导航将是客户端渲染。我认为 getInitialProps 最适合这种情况,相应的文档。
据我了解,getInitialProps 在服务器中运行以进行初始页面渲染,并在使用 next/link 导航时在浏览器中运行。我发现的问题是 getInitialProps 似乎阻止了页面渲染。 (即 getInitialProps 完成后页面更改/渲染)
import axios from 'axios'
function Posts(props)
return (
<div>
<div>Posts:</div>
<div>
JSON.stringify(props)
</div>
</div>
)
Posts.getInitialProps = async (context) =>
const response = await axios.get('https://jsonplaceholder.typicode.com/posts');
// Wait longer to see the effect
// await (new Promise((resolve) =>
// setTimeout(resolve, 5000)
// ))
return
props:
posts: response.data
export default Posts;
我怎样才能像纯 React 一样,先渲染 jsx,然后填写 props?(执行 JSON.stringify(props) 可能一开始会被忽略)
此外,在接下来的 9.3 中,团队引入了 getServerSideProps,推荐使用它而不是 getInitialProps。当它们与 getServerSideProps 在服务器上运行的不同时,它们如何具有可比性?
【问题讨论】:
getInitialProps
的结果作为 props 传递给页面组件。所以next需要等待getInitialProps
解析才能渲染。这就是你所说的“阻止”吗?如果您想使用虚拟数据或其他内容进行初始渲染,则只需进行正常的反应数据获取(例如 useEffect)。
是的,我的意思是阻止。我不能做 csr,因为如果这个页面是初始页面,我需要 s-s-r。我的想法是否有效?
你能解决这个问题吗?我面临着类似的问题。
@Vishu 抱歉回复晚了,我离开了下一个。我记得,这不是我所期望的。我相信社区中的某个人会帮助你度过难关。祝你好运。
【参考方案1】:
根据您的 cmets,您希望在初始页面加载时在服务器上进行提取。但是,如果在页面之间导航,您不希望在等待 getInitialProps
返回时阻止渲染。
一种解决方案是检查您是否在服务器上,然后在getInitialProps
中进行提取。如果在客户端上,不要在getInitialProps
中进行提取,而是在您的渲染方法中使用useEffect
进行提取。
import useEffect from 'react'
import axios from 'axios'
const isServer = () => typeof window === 'undefined'
const getPosts = () =>
return axios.get('https://jsonplaceholder.typicode.com/posts')
.then(response => response.data)
function Posts(posts)
const [renderPosts, setRenderPosts] = useState(posts)
useEffect(() =>
if(posts === null)
getPosts()
.then(setRenderPosts)
, [])
return (
<div>
<div>Posts:</div>
<div>
JSON.stringify(renderPosts)
</div>
</div>
)
Posts.getInitialProps = async (context) =>
if(isServer())
return
posts: await getPosts(),
else
return
posts: null,
export default Posts
顺便说一句,你可能想在这里使用getServerSideProps
,因为它只有在服务器上渲染时才会被调用。然而,当使用getServerSideProps
的页面被渲染时,它实际上会调用服务器以从getServerSideProps
获取数据,即使您使用next/link
进行导航也是如此。来自Next.js 9.3 blog post:
当使用 next/link 在页面之间导航而不是在浏览器中执行 getServerSideProps 时,Next.js 将对服务器进行获取,该服务器将返回调用 getServerSideProps 的结果。
这仍然会导致您想要避免的阻塞问题。
最后一点,这可能不是一个惯用的解决方案。可能有一个更“标准”的解决方案。我只是找不到一个。您可能还可以在页面组件周围使用包装器,它可以以更一致的方式完成所有这些工作。如果你经常使用这种模式,我会推荐它。
【讨论】:
感谢您的回答。是的,我觉得很难找到下一个资源,作为一个新人。您的意思是通过包装页面组件在 _app.js 中执行此操作吗?对于您提供的解决方案,它看起来很棒并且会起作用。但是到服务器还是会有额外的往返,不知道是不是问题。 @Jerryc 您必须与服务器对话才能获取您的数据,这是无法避免的。没有“额外”的往返行程。只需一个电话即可获取您的数据。当服务器获取数据并在初始页面加载时向您发送呈现的页面(包括数据)时,就会发生这种情况。或者,当您使用next/link
导航并直接从 API 获取时会发生这种情况。无论哪种情况,您都会收到一个服务器调用。
抱歉,我还没试过。作为我之前的检查。客户端将始终向道具请求 page.json。但不确定是否返回空对象。如果 getinitialprops 钩子确实返回一个空对象并且客户端仍在请求 json。那么这可能是一个额外的往返。
感谢您的时间和解释。我决定使用纯反应,因为我相信 google 可以很好地反应 spa seo。
@Cully 我遇到了类似的问题,将 api 调用移动到 useEffect 可以防止渲染被阻塞。但是这样做会影响我页面的 SEO 吗?以上是关于Nextjs getInitialProps 阻止了客户端的页面渲染?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 nextjs 的 getInitialProps 无状态组件中访问路由器参数
Nextjs getInitialProps 不适用于 NGINX
NextJS 和 Redux-thunk:出现“错误:“getInitialProps”中的循环结构”
NextJS:我是不是需要使用 getInitialProps 和 next-redux-wrapper 来向所有页面共享状态?
在 NextJS 中是不是可以让自定义 _app.js 读取 slug、getInitialProps 并将这些道具传递给每个组件,包括所有页面?
使用 NextJS 用 Class Components 和 getInitialProps 做 s-s-r,render 方法有未定义的数据