我有一个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 / react编译页面都使用)中,如下所示:
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:include元素中,而不是将它们保留为空样式自闭合标记元素:
<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>
我认为这可能是可以的,并且边缘服务器希望能够识别出相同的内容,但是并没有成功,因为边缘服务器必须使用自闭标签(根据{{3}中的第3.1节) })找到它并进行代码注入。
我们试图使用一些危险的SetInnerHTML解决方案,但同样的事情发生了,添加了结束标记,而不是保留自闭合标记。因此,我怀疑这与我们在JSX代码中的处理方式无关,而是发生在webpack的某处,通过babel编译/编译使其有效成为html5,但不确定如何解决。 看来,要求include标记为自动关闭的ESI规范与仅允许小的指定集合为void(自动关闭)元素的HTML5 specs不兼容。
有人对我如何配置Webpack或Babel保持自动关闭标签有任何想法吗?预先感谢您的帮助!
-----局部工作更新-----
我们已通过将3个静态html文件添加到为服务nextjs / react应用程序的Express服务器的指定静态文件夹中添加了3个静态html文件,从而设法实现了部分解决方法。然后,通过一些客户端javascript将3个文件(head.html,menu.html和foot.html)注入到自定义_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>
)
}
}
这可以通过以下方式工作:边缘服务器现在可以将页眉/菜单/页脚代码正确地注入到未经修改的(无webpack或babel转换的)html文件中,但是当我们添加脚本以将代码插入到由反应页面它没有正确地绑定某些插入的javascript中的某些行为,因此该菜单实际上不起作用。这可能是由于在完成所有其他呈现和JS绑定之后,使用insertAdjacentHTML将其添加到DOM中。所以仍然不是解决方案...