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

Jer*_*ryc 1 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;
Run Code Online (Sandbox Code Playgroud)

我怎样才能像纯 React 一样,先渲染 jsx,然后填写 props?(执行 JSON.stringify(props) 一开始可能会被忽略)

此外,在接下来的 9.3 中,团队引入了 getServerSideProps,推荐使用 getInitialProps。当它们与服务器中运行的 getServerSideProps 不同时,它们如何具有可比性?

Cul*_*lly 7

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

顺便说一下,您可能会想在这里使用getServerSideProps,因为只有在服务器上渲染时才会调用它。但是,当使用 呈现页面时getServerSideProps,它实际上会调用服务器以从中获取数据getServerSideProps,即使您正在使用 进行导航next/link。来自Next.js 9.3 博客文章

当使用 next/link 在页面之间导航而不是在浏览器中执行 getServerSideProps 时,Next.js 将对服务器进行提取,这将返回调用 getServerSideProps 的结果。

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

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