React / nextJS:如何调试SSR react应用程序的不同节点?

时间:2018-12-01 13:21:46

标签: javascript node.js reactjs next.js ssr

我正在运行nextJS应用程序,该应用程序正在运行SSR。

但是当我收到错误消息时:

  

警告:没想到服务器HTML在

中包含

因此,服务器端和客户端节点之间似乎有所不同。如何找到这些差异?

这是示例应用程序的仓库:

https://github.com/jaqua/nextjs-app

只需运行npm installnpm run dev

2 个答案:

答案 0 :(得分:1)

由于手动比较两个html可能很麻烦,具体取决于页面大小,因此建议您首先评估可能出问题的地方,而不要强行使用。根据我在99%的情况下的经验,当您执行以下任一操作时,都会发生SSR不匹配:

  • 包括并呈现了一个组件,该组件在客户端和服务器上的行为方式不同(例如,它们使用全局变量来确定代码在何处运行,并根据该条件有条件地呈现元素)。例如,有一个剪贴板模块仅在客户端上可用,因为它将使用变量window
  • 呈现从异步源获取的数据,该数据仅存在于服务器或客户端上。您需要在初始渲染期间将相同的数据提供给两个用户。

如果在此之后没有发现任何问题,则需要消除。如果错误出现在每个页面上,则很可能是服务器配置错误导致的。例如,您是在做自己的renderToString吗?仔细检查一下,您没有在其中添加额外的嵌套div,该字符串应该就在安装React的元素内。

如果不是这种情况,请尝试一个接一个地提取要渲染的组件,您应该能够很快缩小范围,这会导致问题。

还请记住,每次进行更改时都需要重新启动服务器(除非您在修改源代码时有nodemon或类似的配置重新加载服务器端代码)才能被应用! / p>


作为最后的选择,您可以在服务器响应和客户端首先呈现之间创建自己的diff

1)从您的站点打开控制台,然后粘贴以下内容:

console.log(document.documentElement.innerHTML)

2)单击Copy按钮,然后将其粘贴到client.html文件中

3)现在在您的终端中运行:

curl YOUR_URL > server.html 

4)服务器可能会向您返回html的精简版,因此您需要缩进以使其与客户端html匹配,为此请使用like this

5)完成此操作后,现在可以在终端中运行实际的差异了:

diff server.html client.html

这将列出彼此不同的文件的每个部分。 您可以忽略与Java脚本相关的差异,因为缩进无论如何都很可能是不好的,但要专注于html缩进,您可以在其中发现差异并推断出问题所在。


就您而言,您的翻译系统很可能是问题的根本原因。我建议您遵循更标准的做法,而不要遵循next-i18next,这似乎很新,而且更容易出现问题。显然其他人也拥有an issue的SSR,说实话like this确实很吓人。

我知道它的设置可能会有些麻烦,但这是我自己的i18n配置,只要您指定一个全局变量来确定您所处的环境(或{{1 }}。

__BROWSER__

您只需要使用中间件,从服务器提供语言环境,以便客户端可以从xhr加载它们,并使import i18n from 'i18next' import LanguageDetector from 'i18next-browser-languagedetector' import { reactI18nextModule } from 'react-i18next' i18n .use(require(__BROWSER__ ? 'i18next-xhr-backend' : 'i18next-node-fs-backend')) .use(LanguageDetector) .use(reactI18nextModule) .init({ fallbackLng: 'en', ns: ['translations'], defaultNS: 'translations', interpolation: { escapeValue: false, }, react: { wait: true, }, backend: { loadPath: __BROWSER__ ? '/locales/{{lng}}/{{ns}}.json' : require('path').join(__dirname, '/locales/{{lng}}/{{ns}}.json'), }, }) export default i18n 需要I18nextProvider实例。完整的SSR文档为here

答案 1 :(得分:0)

我将首先查看进入浏览器的html(chrome devtools中的“网络”标签),然后反应可能还是渲染客户端,因此您可以在客户端渲染并比较后查看当前DOM(转到chrome devtools中的“元素”标签->右键单击html元素,然后选择“复制>复制outterHTML”)

如果失败,您可以尝试在浏览器内部添加断点,以对其自身进行反应: 函数canHydrateInstance @ ReactDOMHostConfig.js

https://github.com/facebook/react/blob/c954efa70f44a44be9c33c60c57f87bea6f40a10/packages/react-dom/src/client/ReactDOMHostConfig.js

与同类问题相关的链接:

React 16 warning "warning.js:36 Warning: Did not expect server HTML to contain a <div> in <div>."

https://github.com/zeit/next.js/issues/5367