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

2025-06-04

如何在 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
PREV
异步处理和消息队列简介
NEXT
使用 API 管理和计费提供商实现 API 货币化