如何在 next.js v13 中完全禁用服务器端渲染?

huangapple go评论66阅读模式
英文:

How to entirely disable server-side rendering in next.js v13?

问题

文档中说,我可以通过在需要仅在客户端渲染的文件顶部添加 'use client' 来禁用服务器端渲染。

然而,在实际操作中,我已将此标头添加到项目中的每个文件,并且我看到布局(Layout)和页面(Page)都在服务器端渲染。

我可以通过一个简单的页面来确认这一点:

'use client';

export default () => {
  console.log('SERVER RENDER (page)');

  return (
    <div>test</div>
  );
};

我期望 next dev 不输出 "SERVER RENDER (page)",但它确实输出。

英文:

The documentation says that I can disable server-side rendering by adding 'use client' to the top of files that need to be rendered only client-side.

However, in practice, I've added this header to every file in the project, and I see that both Layout and Page are being rendered server-side.

I can confirm this with a simple page:

'use client';

export default () => {
  console.log('SERVER RENDER (page)');

  return (
    <div>test</div>
  );
};

I would expect next dev to not output "SERVER RENDER (page)", but it does.

答案1

得分: 4

以下是您要翻译的部分:

看起来,即使组件标记为 'use client',它仍然会被预渲染。

客户端组件使您能够为应用程序添加客户端交互性。在 Next.js 中,它们在服务器上预渲染,然后在客户端上进行填充。您可以将客户端组件视为 Next.js 12 和之前版本的工作方式(即 pages/ 目录)。

https://beta.nextjs.org/docs/rendering/server-and-client-components#client-components

@Nikolai 正确指出了这一点,但没有回答如何禁用服务器端渲染。

但是,现在我们知道 Next 13 与 12 的行为相同,我们也可以应用与以前版本中使用的相同填充解决方法

简而言之,您希望将您的布局包装在一个组件中,根据它是否检测到浏览器环境而有条件地呈现元素,例如:

const Dynamic = ({ children }: { children: React.ReactNode }) => {
  const [hasMounted, setHasMounted] = useState(false);

  useEffect(() => {
    setHasMounted(true);
  }, []);

  if (!hasMounted) {
    return null;
  }

  return <>{children}</>;
};

export default ({ children }: { children: React.ReactNode }) => {
  return (
    <html lang="en">
      <head />
      <body>
        <Dynamic>{children}</Dynamic>
      </body>
    </html>
  );
};

显然,请确保知道您在做什么。尽管有例外情况,但这通常是不希望的行为。

如果您正在阅读此页面,您还应该了解路由段配置

// &#39;auto&#39; | &#39;force-dynamic&#39; | &#39;error&#39; | &#39;force-static&#39;
export const dynamic = 'auto';
export const dynamicParams = true;
export const revalidate = false;
// &#39;auto&#39; | &#39;default-cache&#39; | &#39;only-cache&#39; | &#39;force-cache&#39; | &#39;force-no-store&#39; | &#39;default-no-store&#39; | &#39;only-no-store&#39;
export const fetchCache = 'auto';
// &#39;nodejs&#39; | &#39;edge&#39;
export const runtime = 'nodejs';
// &#39;auto&#39; | &#39;global&#39; | &#39;home&#39; | string | string[]
export const preferredRegion = 'auto';

export default function MyComponent() {}
英文:

It looks like even if a component is marked &#39;use client&#39;, it will still be pre-rendered.

> Client Components enable you to add client-side interactivity to your application. In Next.js, they are prerendered on the server and hydrated on the client. You can think of Client Components as how Next.js 12 and previous versions worked (i.e. the pages/ directory).

https://beta.nextjs.org/docs/rendering/server-and-client-components#client-components

@Nikolai pointed this out correctly, but did not answer how to disable SSR.

However, now that we know that Next 13 behaves the same as 12, we can also apply the same hydration workaround that was used in previous versions.

The TLDR is that you want to wrap your layout in a component that conditionally renders the element based on whether it detects the browser environment, e.g.

const Dynamic = ({ children }: { children: React.ReactNode }) =&gt; {
  const [hasMounted, setHasMounted] = useState(false);

  useEffect(() =&gt; {
    setHasMounted(true);
  }, []);

  if (!hasMounted) {
    return null;
  }

  return &lt;&gt;{children}&lt;/&gt;;
};

export default ({ children }: { children: React.ReactNode }) =&gt; {
  return (
    &lt;html lang=&quot;en&quot;&gt;
      &lt;head /&gt;
      &lt;body&gt;
        &lt;Dynamic&gt;{children}&lt;/Dynamic&gt;
      &lt;/body&gt;
    &lt;/html&gt;
  );
};

Obviously, make sure you know what you are doing. This is generally not desired behavior, though there are exceptions.

If you are reading this page, you should also be aware of route segment config:

// &#39;auto&#39; | &#39;force-dynamic&#39; | &#39;error&#39; | &#39;force-static&#39;
export const dynamic = &#39;auto&#39;
export const dynamicParams = true
export const revalidate = false
// &#39;auto&#39; | &#39;default-cache&#39; | &#39;only-cache&#39; | &#39;force-cache&#39; | &#39;force-no-store&#39; | &#39;default-no-store&#39; | &#39;only-no-store&#39;
export const fetchCache = &#39;auto&#39;
// &#39;nodejs&#39; | &#39;edge&#39;
export const runtime = &#39;nodejs&#39;
// &#39;auto&#39; | &#39;global&#39; | &#39;home&#39; | string | string[]
export const preferredRegion = &#39;auto&#39;
 
export default function MyComponent() {}

答案2

得分: 0

根据Next.js文档

客户端组件使您能够向应用程序添加客户端端交互性。在Next.js中,它们在服务器上进行预渲染,然后在客户端上进行填充。

所以你是正确的 - 它们最初在服务器上呈现。

如果您想将静态包提供给客户端,您可以通过将 output: 'export' 添加到您的 next.config.js使用静态导出

英文:

According to the Next.js docs,

> Client Components enable you to add client-side interactivity to your application. In Next.js, they are pre-rendered on the server and hydrated on the client.

So you're correct - they are rendered on the server initially.

If you want to serve a static bundle to your client you can use a static export by adding output: &#39;export&#39; to your next.config.js

答案3

得分: -1

import dynamic from 'next/dynamic'

const DynamicHeader = dynamic(() => import('../components/header'), {
  ssr: false,
})
英文:

import dynamic from 'next/dynamic'

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

huangapple
  • 本文由 发表于 2023年2月10日 11:45:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/75406728.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定