У меня есть приложение nextjs (v7) , в которое мы пытаемся добавить некоторые теги Edge Side Include, к которым были предоставлены:
<esi:include src="https://example.com/head" />
<esi:include src="https://example.com/menu" />
<esi:include src="https://example.com/footer" />
Мы добавили их в наш custom _document.js (который используется всеми скомпилированными страницами nextjs / реагировать) примерно так:
import Document, { Head } from 'next/document'
import React from 'react'
export default class MyDocument extends Document {
render () {
const { html } = this.props
return (
<html>
<Head>
React.createElement('esi:include', { src: 'https://example.com/head }, null)}
</Head>
<body>
React.createElement('esi:include', { src: 'https://example.com/menu }, null)}
<div id='__next' dangerouslySetInnerHTML={{ __html: html }} />
React.createElement('esi:include', { src: 'https://example.com/footer }, null)}
</body>
</html>
)
}
}
Проблема в том, что при компиляции / переносе добавляются закрывающие теги кesi: включайте элементы и не оставляйте их как самозакрывающийся тег-элемент в стиле void:
<html>
<head>
... metas, titles
<esi:include src="https://example.com/head" class="next-head"></esi:include>
</head>
<body>
... stylesheets and preload links
<div>
<esi:include src="https://example.com/menu"></esi:include>
</div>
<div id="__next">
... main app container
<esi:include src="https://example.com/footer"></esi:include>
</div>
</body>
</html>
Я подумал, что это, вероятно, будет хорошо, и Edge-сервер, как мы надеемся, должен распознавать его точно так же, но не какEdge Server должен иметь его с самозакрывающимся тегом (в соответствии с разделом 3.1 здесь, в specs ), чтобы найти его и выполнить внедрение кода.
Мы пытались использовать некоторые опасноSetInnerHTML-решения.но происходит то же самое, закрывающий тег добавляется вместо того, чтобы оставить самозакрывающийся тег как есть.Таким образом, я подозреваю, что это не связано с тем, как мы делаем это в коде JSX, а происходит где-то в веб-пакете, компиляция / перенос бабел, чтобы сделать его действительным html5, но я не уверен, как обойти это.Похоже, что спецификации ESI, для которых требуется, чтобы тег include был самозакрывающимся, и HTML5 specs , которые допускают использование пустого (самозакрывающегося) элемента только небольшого указанного набора, несовместимы.
Есть какие-нибудь идеи относительно того, как я могу настроить Webpack или Babel, чтобы сохранить самозакрывающиеся теги?Заранее благодарим за любую помощь!
----- ЧАСТИЧНАЯ РАБОТА ПО ОБНОВЛЕНИЮ -----
Нам удалось частично обойти эту проблему, добавив 3 статических html-файла.в назначенную статическую папку для экспресс-сервера, который обслуживает приложение nextjs / реагировать.Затем 3 файла (head.html, menu.html и foot.html) внедряются с помощью некоторого клиентского javascript, добавляемого в пользовательский _document.js, например так:
import Document, { Head } from 'next/document'
import React from 'react'
export default class MyDocument extends Document {
render () {
const { html } = this.props
return (
<html>
<Head>
</Head>
<body>
<div id='__next' dangerouslySetInnerHTML={{ __html: html }} />
<script>
var esiHeadReq = new XMLHttpRequest();
esiHeadReq.open('GET', '/static/esi-head.html', true);
esiHeadReq.send(null);
esiHeadReq.onreadystatechange = function () {
if (esiHeadReq.readyState === 4) {
document.head.insertAdjacentHTML('beforeend', esiHeadReq.responseText);
}
}
var esiMenuReq = new XMLHttpRequest();
esiMenuReq.open('GET', '/static/esi-menu.html', true);
esiMenuReq.send(null);
esiMenuReq.onreadystatechange = function () {
if (esiMenuReq.readyState === 4) {
document.body.insertAdjacentHTML('afterbegin', esiMenuReq.responseText);
}
}
var esiFootReq = new XMLHttpRequest();
esiFootReq.open('GET', '/static/esi-foot.html', true);
esiFootReq.send(null);
esiFootReq.onreadystatechange = function () {
if (esiFootReq.readyState === 4) {
document.body.insertAdjacentHTML('beforeend', esiFootReq.responseText);
}
}
</script>
</body>
</html>
)
}
}
Это работает в этом EdgeСервер теперь корректно внедряет код заголовка / меню / нижнего колонтитула в html-файлы (не переносимые через веб-пакеты или вавилонскую оболочку), но когда мы добавили скрипт для вставки кода в основной DOM, используемый страницами реакции, он не связывает некоторые варианты поведенияправильно в каком-то вставленном javascript и поэтому меню на самом деле не работает.Вероятно, это связано с добавлением его в DOM с использованием insertAdjacentHTML после того, как все остальные рендеринг и привязка JS выполнены.Так что все еще не решение ...