Nextjs getInitialProps 阻止了客户端的页面渲染?
Nextjs getInitialProps blocked the page rendering in client side?
由于我想将 SSR 添加到我即将进行的项目中以改善 SEO,因此我想接下来尝试一下。我想要的是仅将 SSR 用于初始页面,站点中的其余导航将由客户端呈现。我看到 getInitialProps 最适合这种情况,相应的文档。
据我了解,getInitialProps 在服务器中是 运行 用于初始页面呈现,在使用 next/link 导航时在浏览器中是 运行。我发现的问题是 getInitialProps 似乎阻止了页面呈现。 (即 getInitialProps 完成后的第 changed/rendered 页)
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
到 return.
时阻塞
一种解决方案是检查您是否在服务器上,然后在 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:
When navigating between pages using next/link instead of executing getServerSideProps in the browser Next.js will do a fetch to the server which will return the result of calling getServerSideProps.
这仍然会导致您想要避免的阻塞问题。
最后一点,这可能不是一个惯用的解决方案。可能还有更多 "standard" 的解决方案。我只是没能找到一个。您可能还可以在页面组件周围使用一个包装器,它可以以更一致的方式完成所有这些工作。如果你经常使用这种模式,我会推荐。
由于我想将 SSR 添加到我即将进行的项目中以改善 SEO,因此我想接下来尝试一下。我想要的是仅将 SSR 用于初始页面,站点中的其余导航将由客户端呈现。我看到 getInitialProps 最适合这种情况,相应的文档。
据我了解,getInitialProps 在服务器中是 运行 用于初始页面呈现,在使用 next/link 导航时在浏览器中是 运行。我发现的问题是 getInitialProps 似乎阻止了页面呈现。 (即 getInitialProps 完成后的第 changed/rendered 页)
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
到 return.
一种解决方案是检查您是否在服务器上,然后在 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:
When navigating between pages using next/link instead of executing getServerSideProps in the browser Next.js will do a fetch to the server which will return the result of calling getServerSideProps.
这仍然会导致您想要避免的阻塞问题。
最后一点,这可能不是一个惯用的解决方案。可能还有更多 "standard" 的解决方案。我只是没能找到一个。您可能还可以在页面组件周围使用一个包装器,它可以以更一致的方式完成所有这些工作。如果你经常使用这种模式,我会推荐。