Nextjs:由 Prismjs 突出显示的服务器渲染代码块不匹配,并由于 class 属性上的前导空格而导致重新渲染

Nextjs: server rendered code blocks highlighted by Prismjs mismatches and causes re-render due to leading whitespace on class attribute

我正在尝试使用 Prismjs 实现语法突出显示(标记化)代码块的服务器端渲染(注意:我知道如何通过 useEffectrefs 使用客户端渲染来实现此目的,我使用 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 属性上:

这导致(除了无意义的昂贵重新渲染之外)不愉快的布局偏移,通过将硬编码 font-size 像素添加到 <pre> 元素暂时修复。

我偶尔会收到一些警告,无论是服务器和客户端道具不匹配(现在无法重现)还是 Extra attributes from the server: class – 但仅当 运行ning next dev , 而不是 运行ning next build && next start.

已在最新版本的 Nextjs 和 Prism 上进行测试。

我从 Prismjs source code:

中得到了答案
if (parent && parent.nodeName.toLowerCase() === 'pre') {
    parent.className = parent.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language;
}

这就是空格的来源。很明显,为什么它在这里(作为字符串连接的填充)。

一个临时的 hacky 修复是在 <pre> 元素的 className 中添加一个前导空格。

<pre
   data-language={language}
   className={` language-${language}`}
>

但很明显,这不是使用PrismjsSSR的好方法。