React/nextJS: How to debug different nodes of SSR react application? React/nextJS: How to debug different nodes of SSR react application? node.js node.js

React/nextJS: How to debug different nodes of SSR react application?


As comparing two html manually can be rather cumbersome depending on the size of your page, it's advised to first assess what could be wrong rather than brute-forcing. From my experience in 99% of the cases an SSR mismatch occurs when you either:

  • Included and rendered a Component which doesn't behave the same way on the client and the server (e.g they use global variables to determine where the code is being run and conditionally render elements based on that). For example there was a clipboard module that would only work on the client because it would use a variable of window.
  • Rendering of data fetched from an asynchronous source which is only present on either the server or the client. You need to make the same data available for both during the initial render.

If nothing comes out to mind after this, you need to proceed by elimination. In case the error occurs on every page, it is likely to be a result of a misconfiguration of the server. For example, are you doing your own renderToString? Double check you didn't add an extra nested div in there, the string should be right inside the element you mount React on.

If that is not the case, try to extract one by one the components you are rendering, and you should be able to narrow down pretty quickly which is causing your issue.

Also keep in mind that you would need to restart your server every-time you make a change (unless you have a nodemon or similar config reloading the server-side code when you modify your source) for it to be applied!


As a last resort, you could potentially make your own diff between the server response and the client first render.

1) Open your console from your site, and paste the following:

console.log(document.documentElement.innerHTML)

2) Click on the Copy button, and paste that in a client.html file

3) Now run in your terminal:

curl YOUR_URL > server.html 

4) It's likely the server will return you a minified version of your html, so you need to indent it in order to make it match with your client html, use something like this for that purpose.

5) Once you've done this, you can now run the actual diff in your terminal:

diff server.html client.html

This will list you every part of the files that differ between each other.You can ignore diffs related to Javascript as the indenting will most likely be bad anyway, but concentrate on the html ones, where you might be able to spot differences and infer what is going wrong.


In your case, your translation system is likely to be the root cause of the issue. I would advice to follow more standard practices rather than next-i18next which seem pretty new and more likely to have problems. Someone else apparently also has an issue with SSR, and to be honest stuff like this is quite scary.

I know it can look a bit troublesome to setup, but here is my own i18n config which can be required either on the server or the client provided you specify a global variable to determine one which environment you are (here __BROWSER__).

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

You simply need to use the middleware, serve the locales from your server so the client can load them from xhr and have the I18nextProvider require the i18n instance. The full SSR docs are here.


I would start by looking at the html that get's to the browser(network tab in chrome devtools), then react is probably rendering client side anyway, so you can see the current DOM after the client side render and compare (go to elements tab in chrome devtools -> right click the html element and select "copy> copy outterHTML")

If that fails, you can try adding breakpoints in the browser inside react itself:function canHydrateInstance @ ReactDOMHostConfig.js

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

possibly relevant links to same kind of issue:

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