React / nextJS: Как отлаживать разные узлы приложения SSR реагировать? - PullRequest
0 голосов
/ 01 декабря 2018

Я запускаю приложение nextJS, которое запускает SSR.

Но когда я получаю сообщение об ошибке:

Предупреждение: не ожидал, что серверный HTML содержит

in
.

Так что, похоже, существует разница между серверной и клиентской сторонами.Как я могу найти эти различия?

Это репозиторий примера приложения:

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

Просто запустите npm install и npm run dev

Ответы [ 2 ]

0 голосов
/ 08 декабря 2018

Поскольку сравнение двух html вручную может быть довольно громоздким в зависимости от размера вашей страницы, рекомендуется сначала оценить, что может быть не так, а не грубым принуждением.Исходя из моего опыта, в 99% случаев несоответствие SSR происходит, когда вы либо:

  • включили и представили компонент, который не ведет себя одинаково на клиенте и сервере (например, они используют глобальныйпеременные для определения места выполнения кода и условного отображения элементов на его основе).Например, был модуль буфера обмена, который работал бы только на клиенте, потому что он использовал бы переменную window.
  • Отображение данных, извлеченных из асинхронного источника, который присутствует только на сервере или на клиенте.,Вам нужно сделать одинаковые данные доступными для обоих во время начального рендеринга.

Если после этого ничего не приходит в голову, вам нужно продолжить удаление.Если ошибка возникает на каждой странице, это может быть следствием неправильной настройки сервера.Например, вы делаете свой собственный renderToString?Дважды проверьте, что вы не добавили туда дополнительный вложенный div, строка должна быть прямо внутри элемента, на котором вы монтируете React.

Если это не так, попробуйте извлечь один за другим компоненты, которые вы используете.рендеринг, и вы должны быть в состоянии довольно быстро сузить, что вызывает вашу проблему.

Также имейте в виду, что вам нужно будет перезапускать сервер каждый раз, когда вы вносите изменения (если у вас нет nodemon илипохожий конфиг, перезагружающий код на стороне сервера при изменении исходного кода) для его применения!


В качестве последнего средства вы могли бы потенциально сделать свой собственный diff между ответом сервера и клиентомпервый рендер.

1) Откройте консоль со своего сайта и вставьте следующее:

console.log(document.documentElement.innerHTML)

2) Нажмите кнопку Copy и вставьте ее в client.htmlfile

3) Теперь запустите в своем терминале:

curl YOUR_URL > server.html 

4) Скорее всего, сервер вернет вам уменьшенную версию вашего html, поэтому вам нужно сделать отступ, чтобы сделать makЕсли он соответствует вашему клиентскому html, используйте для этой цели что-то вроде , например .

5) После того, как вы это сделаете, вы можете запустить фактический diff в вашем терминале:

diff server.html client.html

В нем будут перечислены все части файлов, которые отличаются друг от друга.Вы можете игнорировать различия, связанные с Javascript, поскольку отступы, скорее всего, в любом случае будут плохими, но сконцентрируйтесь на HTML, где вы сможете найти различия и сделать выводы о том, что идет не так.


В вашемВ этом случае ваша система перевода, вероятно, является основной причиной проблемы.Я бы посоветовал следовать более стандартным практикам, а не next-i18next, которые кажутся довольно новыми и с большей вероятностью имеют проблемы.У кого-то еще, очевидно, также есть проблема с SSR, и, честно говоря, вроде этого довольно страшно.

Я знаю, это может показаться немного проблематичным при настройке,но вот моя собственная конфигурация i18n, которая может потребоваться либо на сервере, либо на клиенте, при условии, что вы указываете глобальную переменную для определения среды, в которой вы находитесь (здесь __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

Вам просто нужночтобы использовать промежуточное программное обеспечение, обслуживайте локали с вашего сервера, чтобы клиент мог загрузить их из xhr и получить для I18nextProvider экземпляр i18n.Полные документы по SSR: здесь .

0 голосов
/ 07 декабря 2018

Я бы начал с просмотра html-кода, который попадает в браузер (вкладка сети в chrome devtools), а затем реагировал, вероятно, в любом случае на стороне клиента, так что вы можете увидеть текущий DOM после того, как на стороне клиента отобразится и сравнить (перейти кВкладка «Элементы» в Chrome Devtools -> щелкните правой кнопкой мыши элемент html и выберите «copy> copy outterHTML»)

Если это не удастся, вы можете попробовать добавить точки останова в браузере внутри самой реакции: функция canHydrateInstance @ ReactDOMHostConfig.js

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

возможно релевантные ссылки на проблему такого же типа:

React 16 warning "warning.js: 36 Предупреждение: не ожидал, что сервер HTML содержит

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

...