Nextjs getInitialProps阻止了客户端的页面渲染?

时间:2020-03-16 15:13:59

标签: javascript seo next.js

由于我想将SSR添加到我即将进行的项目中以改善SEO,因此我想接下来尝试一下。我想要的是仅对初始页面使用SSR,而网站中的其余导航将是客户端渲染。在这种情况下,我认为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,然后填写道具?(首先会忽略执行JSON.stringify(props))

此外,在接下来的9.3版中,该团队引入了getServerSideProps,建议在getInitialProps上使用。当它们与服务器上运行的getServerSideProps不同时,如何比较?

1 个答案:

答案 0 :(得分:3)

根据您的评论,您希望在初始页面加载时在服务器上进行提取。但是,如果在页面之间导航,则您不希望在等待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的结果。

这仍然会导致您要避免的阻止问题。

最后一点,这可能不是惯用的解决方案。可能会有更“标准”的解决方案。我只是找不到一个。您可能还可以在页面组件周围使用包装器,以更一致的方式完成所有这些操作。如果您经常使用这种模式,建议您这样做。