是否可以在Next.js中禁用某些页面的服务器端渲染(SSR)?例如,我有一个产品描述页面,在这个页面上我使用SSR进行SEO,但我也有一个包含项目或产品列表的页面,我可以对其进行筛选,对于该页面,我不想使用SSR,因为每次都会动态生成,如何在此页面上禁用SSR?
是否可以在Next.js中禁用某些页面的服务器端渲染(SSR)?例如,我有一个产品描述页面,在这个页面上我使用SSR进行SEO,但我也有一个包含项目或产品列表的页面,我可以对其进行筛选,对于该页面,我不想使用SSR,因为每次都会动态生成,如何在此页面上禁用SSR?
dynamic()
函数也可以在没有动态导入的情况下使用:
// components/NoSsr.jsx
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
})
任何放在这个组件中的内容都不会在服务器端渲染的源代码中显示。例如:
// inside the page you want to disable SSR for
import NoSsr from "components/NoSsr";
Contact me at <NoSsr>email@example.com</NoSsr>
_app
一起使用。 - Eric Burel懒加载组件并禁用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 />
这将禁用 next.js SSR,在您的 _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,
});
const isServer = () => typeof window === `undefined`;
const Page = () => isServer() ? null : (
<>
<YourClientSideComponent />
</>
);
这是关于“页面”级别的内容。isServer()
可以防止在服务器端渲染任何内容。如果你愿意,你也可以在组件级别上防止ssr:
const isServer = () => typeof window === `undefined`;
const Page = () =>(
<>
{ !isServer() && <YourClientSideComponent /> }
</>
);
!isServer
前面的 "." 是有意为之吗?这是无效的 JavaScript 语法。 - Dawson B完全基于Erik Hofer的回答,您可以创建一个HOC来包装您的页面或其他组件。
import dynamic from 'next/dynamic';
import React from 'react';
const withNoSSR = (Component: React.FunctionComponent) => dynamic(
() => Promise.resolve(Component),
{ ssr: false },
);
export default withNoSSR;
import React from 'react';
import withNoSSR from './withNoSSR';
function SomePage() {
return (
<div>Only renders in the browser</div>
);
}
// wrap with HOC on export
export default withNoSSR(SomePage);
我们还可以使用react-no-ssr React组件。
假设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>
);
react-no-ssr
因为一些 TypeScript 问题而无法正常工作。import { ReactNode, useEffect, useLayoutEffect, useState } from 'react'
const DefaultOnSSR: React.FC = () => null
export const NoSSR: React.FC<{ children: ReactNode; onSSR?: ReactNode }> = ({ children, onSSR = <DefaultOnSSR /> }) => {
const [onBrowser, setOnBrowser] = useState(false)
useLayoutEffect(() => {
setOnBrowser(true)
}, [])
return <>{onBrowser ? children : onSSR}</>
}
如果您想避免像下面这样的服务器端渲染,可以在任何地方使用:
const MyPage = () => (
<div>
<h2>My Blog Post</h2>
<hr />
<NoSSR>
<Comments />
</NoSSR>
</div>
);
我刚刚想出了一个解决方案,这个方案是基于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>
const useClientCheck =() => { const [isClient, setIsClient] = useState(false); useEffect(() => { setIsClient(true)}, []); return isClient }
- Eric Burel另一个我认为最简单的解决方案是只使用process.browser
,这将仅在客户端运行时为真。
<div>
{
process.browser && <Hidden />
}
</div>
NoSsr
组件。 - guest