关于prism-react-renderer在nextjs中的动态导入

191 阅读1分钟

prism-react-renderer是基于prism对于React的封装,解决了prism在更新code的同时破坏了dom结构,从而影响到diff算法的问题。
prism-react-renderer可以使code更新的时候,不会让整个组件的dom更新。

prism-react-renderer本身支持的语言是有限的,如果想要支持更多语言,需要从prism中导入。

在普通的React应用中导入示例如下:

github:github.com/FormidableL…
demo:github.com/FormidableL…

在nextjs中导入的示例如下:
使用next/dynamic进行动态导入。

import dynamic from 'next/dynamic';
import { useDarkMode } from '@/hooks/useDarkMode';
import { Highlight, themes, Prism } from 'prism-react-renderer';
import { useEffect, useMemo } from 'react';
import CopyButton from '../ui/CopyButton';

interface CodeEditorProps {
  content: string;
  language: string;
}

const CodeEditor: React.FC<CodeEditorProps> = ({ content, language }) => {
  const { darkMode } = useDarkMode();

  const codeTheme = useMemo(() => {
    return darkMode ? themes.nightOwl : themes.nightOwlLight;
  }, [darkMode]);

  useEffect(() => {
    // Example of importing a custom language directly from Prism
    (typeof global !== 'undefined' ? global : window).Prism = Prism;
    // @ts-ignore
    language && dynamic(import(`prismjs/components/prism-${language}`), { ssr: false });
  }, [language]);

  return (
    <div className="relative h-full">
      <Highlight theme={codeTheme} code={String(content).replace(/\n$/, '')} language={language}>
        {({ className, style, tokens, getLineProps, getTokenProps }) => (
          <pre className={`${className} p-4 overflow-auto h-full`} style={style}>
            {tokens.map((line, i) => (
              <div key={i} {...getLineProps({ line })}>
                {line.map((token, key) => (
                  <span key={key} {...getTokenProps({ token })} />
                ))}
              </div>
            ))}
          </pre>
        )}
      </Highlight>
      <CopyButton size="xxs" textToCopy={content} className="absolute right-3 top-2" />
    </div>
  );
};

export default CodeEditor;