发布于 2025-12-07 2 阅读
0

如何在 Next.js 中禁用服务器端渲染 (SSR)?为什么要在 Next.js 中禁用 SSR?如何在 Next.js 中禁用 SSR?路由和其他高级功能的说明

如何在 Next.js 中禁用服务器端渲染 (SSR)

为什么要在 Next.js 中禁用 SSR?

如何在 Next.js 中禁用 SSR?

关于路由和其他高级功能的说明

了解如何在 Next.js 中禁用 SSR 并使用它来替换 Create React App 或任何自定义工具。


Next.js 是我最喜爱的 React 应用开发工具。它提供一流的开发体验。此外,它还拥有大量实用功能,可提高生产效率并优化您的应用:

  • 静态和服务器渲染
  • TypeScript 支持
  • 多个入口点
  • 捆绑拆分和摇树

然而,过去我并不想将它用于我所有的 React 应用。默认情况下,Next.js 在没有服务器端渲染 (SSR) 的情况下无法工作。当我的应用不需要 SSR 时,我更喜欢使用像 Create React App 这样的非 SSR 解决方案,因为 SSR 已经给我带来了很多不必要的问题。

然后,有一天,React Query 的作者 Tanner Linsley 在 Twitter 上发帖称,他正在使用不带 SSR 的 Next.js 来替代 Create React App:

我太兴奋了!研究了一番之后,我终于可以自己做了。🤯

为什么要在 Next.js 中禁用 SSR?

在某些情况下,React 应用程序的 SSR 是必要的:

  • 应用程序的内容需要在搜索结果(SEO)中排名靠前。
  • 您需要社交媒体预览(Facebook、Twitter、Slack 等)。
  • 您需要它可以为您的用户提供的额外速度优化。

然而,使用 SSR 有多个权衡和挑战:

  • 你需要一个复杂的托管环境。你不能直接将应用上传到服务器或 CDN。你需要 Node.js 服务器进行服务端渲染。这不仅增加了复杂性,也增加了成本。
  • 你需要确保你的代码在浏览器和服务器(Node.js)上都能正常工作。这会使调试更加困难,并且在某些情况下会限制你的操作。例如,你不能使用 localStorage 来存储授权信息,而需要将其传入 cookie 中,并使用一个可以在服务器和浏览器上运行的 cookie 库。

  • 它会影响你的应用程序架构。例如,服务器端渲染需要在单次渲染中完成,因此你需要在一个位置(例如getInitialProps)获取页面的所有数据。这一要求使得使用 Redux 或 React Query 等库获取数据变得复杂,并且经常导致代码重复。

如果您不需要 SSR,这些权衡就不值得。基本上,您应该考虑为所有需要登录才能使用 UI 的应用禁用 SSR。

启发式:如果您的应用程序需要登录,您可能应该禁用 SSR。

如何在 Next.js 中禁用 SSR?

npx create-next-app让我们看一下为新的 Next.js 应用程序(使用 创建)禁用 SSR 的步骤。

步骤 1:将所有请求重写为pages/index.js

Next.js 支持添加重定向next.config.js。在项目根目录中创建一个文件,并在其中添加以下配置:



module.exports = {
  target: "serverless",
  async rewrites() {
    return [
      // Rewrite everything to `pages/index`
      {
        source: "/:any*",
        destination: "/",
      },
    ];
  },
};


Enter fullscreen mode Exit fullscreen mode

这些重定向仅在开发环境中有效。在生产环境中,您需要拥有像 NGINX 这样的代理服务器,或者使用托管平台的功能(例如Netlify 的重定向)来执行这些重定向。

步骤 2:禁用页面内容的 SSR

要禁用页面内容的 SSR,我们需要添加以下代码pages/_app.js:



import '../styles/globals.css'

function SafeHydrate({ children }) {
  return (
    <div suppressHydrationWarning>
      {typeof window === 'undefined' ? null : children}
    </div>
  )
}

function MyApp({ Component, pageProps }) {
  return <SafeHydrate><Component {...pageProps} /></SafeHydrate>
}

export default MyApp


Enter fullscreen mode Exit fullscreen mode

在上面的代码中,我们将页面内容包装到一个名为 的组件中SafeHydrate,这样就可以防止页面内容在服务器上渲染。让我们来看看上面的代码到底做了什么。

window使用 Next.js,您可以通过检查对象是否来检查我们是否在服务器上undefined。



if(typeof window === 'undefined') {
  // This code will only execute on the server 
  // and not in the browser
}


Enter fullscreen mode Exit fullscreen mode

但是,我们不能直接将代码包装到这个if语句中。如果你尝试这样做,你会注意到 React 会在控制台中生成一个恼人的 hydration mismatch 警告:Warning: Expected server HTML to contain a matching <div> in <div>.如果服务器 HTML 与浏览器渲染的 HTML 不同,就会发生这种情况。

在我们的例子中,忽略此警告是安全的。为了保持整洁,我们希望完全隐藏控制台中的警告。这可以通过使用 prop 渲染一个 div 来实现suppressHydrationWarning。为了提高可读性,我们SafeHydrate为此创建了一个单独的组件,并将页面组件包装在其中。

步骤 3:检查一切是否正常npm run dev

现在,npm run dev在终端中运行。服务器在http://localhost:3000/运行后,你应该能够访问任何 URL(例如http://localhost:3000/some/random/path)并在那里看到 index.js 的内容。

截图于 2020-12-10 12.20.29

成功!🎉

步骤 4:使用next export

我们希望将应用程序部署为静态包,以便无需 Node.js 服务器即可提供服务。为此,Next.js 提供了命令next export。它将在目录中创建应用程序的静态版本out。

要使用该命令,请像这样更新“build”脚本package.json:



"scripts": {
  ...
  "build": "next build && next export"
  ...
}


Enter fullscreen mode Exit fullscreen mode

现在,运行npm run build。当你看到消息 时Export successful,恭喜!你现在在目录中有一个可以运行的静态 Next.js 应用out。🎉

您可以从此Github 存储库查看整个示例应用程序

关于路由和其他高级功能的说明

路由

如果您没有运行服务器,Next.js 不支持动态路由。您需要一个类似 的路由器react-router。设置方法与其他工具(例如 Create React App)相同。

更新<title>和其他<head>标签

您不需要添加类似的内容react-helmet来更新head,Next.js<Head />组件就可以工作。

拥有多个独立页面

如果需要,您仍然可以使用 Next.js 页面,将多个不同的页面作为应用的单独入口点。这将减少每个路由的 bundles 大小,并加快开发环境速度,因为进行更改时只会构建应用的一部分。

例如,如果您有一个页面,/accounts您可以创建一个文件pages/account.js并添加相应的重写:



module.exports = {
  target: "serverless",
  async rewrites() {
    return [
      // Rewrite everything under `/account/ to `pages/account`
      {
        source: "/account/:any*",
        destination: "/account",
      },
      // Rewrite everything else to `pages/index`
      {
        source: "/:any*",
        destination: "/",
      },
    ];
  },
};
```

# How's this different from using Next.js `getStaticProps` with `getStaticPaths`?

Using `getStaticProps` with `getStaticPaths` allows you to do Static Site Generation (SSG). This means that all the pages in your app are generated as individual `.html`-files when you run `npm run build`. 

SSG is awesome, but has a single big limitation: **You need to know all the paths your app has ahead of time**. This is not possible with many apps that have tons of user-specific paths like `/my-payments/123121521241`. 

With the approach described in this article, you can use a dynamic router like `react-router` with Next.js just like you would with Create React App or any traditional single-page app.

# Additional Resources:

- [This wonderful gist by @tannerlinsley](https://gist.github.com/tannerlinsley/65ac1f0175d79d19762cf06650707830)
Enter fullscreen mode Exit fullscreen mode
文章来源:https://dev.to/apkoponen/how-to-disable-server-side-rendering-ssr-in-next-js-1563