【问题标题】:Next js - disable server side rendering on some pagesNext js - 在某些页面上禁用服务器端渲染
【发布时间】:2019-04-07 22:56:56
【问题描述】:

是否可以使用 Next js 在某些页面上禁用 ssr?例如,我有一个带有产品描述的页面,在该页面上我使用 ssr 进行 SEO,但我也有一个页面,其中包含我可以过滤的项目或产品列表,对于该页面,我不想使用 ssr,因为这页面每次都是动态生成的,如何关闭这个页面的ssr?

【问题讨论】:

  • 如果你使用material ui,有一个NoSsr组件可以直接开箱使用

标签: reactjs next.js server-side-rendering


【解决方案1】:

延迟加载组件并禁用 SSR:https://nextjs.org/docs/advanced-features/dynamic-import#with-no-ssr

import dynamic from 'next/dynamic'

const DynamicComponentWithNoSSR = dynamic(() => import('../components/List'), {
  ssr: false
})

export default () => <DynamicComponentWithNoSSR />

【讨论】:

  • &lt;div&gt; 不是必需的。
  • 如果里面有没有ssr元素的子元素,会发生什么?我的顶级元素需要 no ssr 来容纳其他孩子,这会影响我的 SEO 和性能吗?
【解决方案2】:

这是一个迟到的答案,但如果有人遇到这个:

const isServer = () => typeof window === `undefined`;

const Page = () => isServer() ? null : (

  <> 
      <YourClientSideComponent />
  </>
);

这是在“页面”级别。 isServer() 防止在服务器端呈现任何内容。如果您愿意,您也可以在组件级别阻止 ssr:

const isServer = () => typeof window === `undefined`;

const Page = () =>(

  <> 
      { !isServer() && <YourClientSideComponent /> }
  </>
);

【讨论】:

  • 是“.”在!isServer 之前是故意的?这是无效的 JavaScript 语法。
  • 我让它在 Next.js 项目中工作,其中包含样式组件,但并不总是按要求工作。不知道为什么!!公认的解决方案是最合适的
  • 这将在服务器渲染和客户端渲染之间造成不匹配,这实际上并没有禁用渲染。
【解决方案3】:

dynamic() 函数也可以在没有动态导入的情况下使用:

import dynamic from 'next/dynamic'
import React from 'react'

const NoSsr = props => (
  <React.Fragment>{props.children}</React.Fragment>
)

export default dynamic(() => Promise.resolve(NoSsr), {
  ssr: false
})

任何包裹在这个组件中的东西都不会在 SSR 源中可见。

Contact me at <NoSsr>email@example.com</NoSsr>

【讨论】:

  • 效果很好,可以用来将包裹在_app.js中进行调试
  • 非常好,因为您也可以将它与_app 一起使用。
  • 但有一个限制:它可能对代码的加载方式有其他副作用。一个纯 React 解决方案可能就足够了(例如 anwser stackoverflow.com/a/57512843/5513532 中所述)
【解决方案4】:

这是我刚刚根据 React 文档中提到的内容提出的解决方案:https://reactjs.org/docs/react-dom.html#hydrate

class ClientOnly extends React.Component {
  state = {
    isClient: false,
  };

  componentDidMount() {
    this.setState({
      isClient: true,
    });
  }

  render() {
    const { isClient } = this.state;
    const { children } = this.props;

    return isClient ? children : false;
  }
}

然后您可以用它包装任何组件/块,它不会在服务器上呈现。例如

<ClientOnly>You're logged in as {name}</ClientOnly>

这也可以防止以下 React.hydrate 警告“警告:预期的服务器 HTML 将包含匹配项。”

【讨论】:

  • 我认为与钩子等效的情况如下:const useClientCheck =() =&gt; { const [isClient, setIsClient] = useState(false); useEffect(() =&gt; { setIsClient(true)}, []); return isClient }
【解决方案5】:

我们也可以使用react-no-ssrReact 组件。

假设 Comments 是我们的客户端唯一组件。现在我们只需要在客户端上渲染它。以下是我们的做法。

import React from 'react';
import NoSSR from 'react-no-ssr';
import Comments from './comments.jsx';

const MyPage = () => (
  <div>
    <h2>My Blog Post</h2>
    <hr />
    <NoSSR>
      <Comments />
    </NoSSR>
  </div>
);

【讨论】:

    【解决方案6】:

    另一个我相信最简单的解决方案是只使用process.browser,这只有在客户端运行时才适用。

    <div>
      {
        process.browser && <Hidden />
      }
    </div>
    

    【讨论】:

      【解决方案7】:

      把它放在你的 _app.tsx 上

      import type { AppProps } from "next/app";
      import dynamic from "next/dynamic";
      import React from "react";
      
      const App = ({ Component, pageProps }: AppProps) => {
        return <Component {...pageProps} />;
      };
      
      export default dynamic(() => Promise.resolve(App), {
        ssr: false,
      });
      

      【讨论】:

        【解决方案8】:

        你也可以使用react-no-ssr

        import NoSSR from 'react-no-ssr';
        
        const Component = props => (
          <React.Fragment>{props.children}</React.Fragment>
        )
        
        export default () => <NoSSR><Component /></NoSSR>
        

        【讨论】:

          猜你喜欢
          • 2021-11-20
          • 2021-03-30
          • 2023-01-19
          • 2021-10-30
          • 1970-01-01
          • 1970-01-01
          • 2021-09-24
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多