如何解决Nextjs:由 Prismjs 突出显示的服务器渲染代码块不匹配并由于类属性上的前导空格而导致重新渲染
我正在尝试使用 Prismjs 实现语法高亮(标记化)代码块的服务器端呈现(注意:我知道如何通过 useEffect
和 refs
使用客户端呈现来实现这一点,并且我使用 prism-react-renderer 完成了这项工作。我正在寻找“裸” Prismjs 和 SSR 的解决方案。
// codeExamples = array of some code strings
const Code = ({ code,language }) => {
const html = Prism.highlight(code,Prism.languages[language],language);
return (
<pre
data-language={language}
className={`language-${language}`}
>
<code
dangerouslySetInnerHTML={{
__html: html,}}
/>
</pre>
);
};
export default function Home() {
return codeExamples.map((example,i) => (
<Code
language="javascript"
code={example}
key={i}
></Code>
));
}
它在某种程度上确实有效,但我遇到了一个问题:代码块被短暂地重新渲染,可能是因为 class
属性上的前导空格:
- 第一次渲染:
class="language-javascript"
- 第二次渲染:
class=" language-javascript
这会导致(除了无意义的昂贵的重新渲染之外)令人不快的布局偏移,通过将像素中的硬编码 font-size
添加到 <pre>
元素来临时修复。
我偶尔会收到一些警告,可能是服务器和客户端道具不匹配(现在无法重现)或 Extra attributes from the server: class
– 但仅在运行 next dev
时,而不是在运行 {{1} 时}}。
在最新版本的 Nextjs 和 Prism 上进行测试。
解决方法
我从深入了解 sub
source code 中得到了答案:
Prismjs
这是空格的来源。很明显,它为什么在这里(作为字符串连接的填充)。
一个临时的 hacky 修复是在 if (parent && parent.nodeName.toLowerCase() === 'pre') {
parent.className = parent.className.replace(lang,'').replace(/\s+/g,' ') + ' language-' + language;
}
元素上的 className
中添加一个前导空格。
<pre>
但很明显,这不是将 <pre
data-language={language}
className={` language-${language}`}
>
用于 SSR 的好方法。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。