如何在Next.js服务端使用React-Syntax-Highlighter

react-syntax-highlighter 在nextjs服务端 怎么用

在Next.js服务端(服务器端)使用react-syntax-highlighter,需要使用next/dynamic和no-ssr组件来加载它。

首先,您需要安装必要的依赖项:

npm install react-syntax-highlighter next/dynamic no-ssr

然后,在页面中使用next/dynamicno-ssr组件来加载react-syntax-highlighter。示例代码如下:

import dynamic from 'next/dynamic'
import NoSSR from 'react-no-ssr'

const SyntaxHighlighter = dynamic(
  () => import('react-syntax-highlighter'),
  { ssr: false }
)

function Example() {
  return (
    <NoSSR>
      <SyntaxHighlighter language="javascript" style={docco}>
        {`function greet(name) {
          console.log(\`Hello, \${name}!\`);
        }`}
      </SyntaxHighlighter>
    </NoSSR>
  )
}

这里,我们使用了next/dynamic来异步加载react-syntax-highlighter组件,并使用NoSSR来防止在服务器端呈现高亮显示的代码。

请注意,我们将ssr属性设置为false,以便在服务器端不会呈现组件。同时,在组件内部,我们传递了languagestyle属性来指定语言和样式。

这里 docco 样式怎么导入的

doccoreact-syntax-highlighter 提供的一种内置样式,您可以通过以下方式导入:

import { docco } from 'react-syntax-highlighter/dist/cjs/styles/hljs'

然后,在代码高亮组件中使用它即可:

<SyntaxHighlighter language="javascript" style={docco}>
  {`function greet(name) {
    console.log(\`Hello, \${name}!\`);
  }`}
</SyntaxHighlighter>

当然,react-syntax-highlighter 还提供了其他内置样式,详见其文档。您还可以选择自定义样式,方法是在 styles 文件夹下创建一个新的样式文件并导出样式对象。然后,将其导入并传递给代码高亮组件的 style 属性即可。

样式是否也要动态导入?

对于样式,如果您选择使用 react-syntax-highlighter 提供的内置样式,可以直接在页面中导入并传递给代码高亮组件的 style 属性。例如,要使用 docco 样式,在页面中导入它:

import { docco } from 'react-syntax-highlighter/dist/cjs/styles/hljs'

然后,将其传递给代码高亮组件的 style 属性即可:

<SyntaxHighlighter language="javascript" style={docco}>
  {`function greet(name) {
    console.log(\`Hello, \${name}!\`);
  }`}
</SyntaxHighlighter>

对于自定义样式,您需要将其导入到页面组件中,并将其传递给代码高亮组件的 style 属性。样式通常是一个 JavaScript 对象,可以通过 import 语句从单独的文件或模块中导入。

还有一种情况,就是你打算使用styled-components来为您的应用程序创建动态主题。在这种情况下,您可以使用withTheme高阶组件,该组件允许您从主题中访问颜色和其他样式变量。然后,您可以将这些变量传递给react-syntax-highlighter的样式对象。以下是示例代码:

import styled, { withTheme } from 'styled-components'
import { docco as base16Docco } from 'react-syntax-highlighter/dist/cjs/styles/hljs'

const Docco = styled(base16Docco)`
  .hljs-comment,
  .hljs-quote {
    color: ${props => props.theme.colors.secondary};
  }

  ...
`

const Highlight = ({ theme }) => (
  <SyntaxHighlighter language="javascript" style={Docco} customStyle={{ backgroundColor: theme.colors.primary }}>
    {`function greet(name) {
      console.log(\`Hello, \${name}!\`);
    }`}
  </SyntaxHighlighter>
)

export default withTheme(Highlight)

在上面的代码中,我们使用 styled-components 来创建一个名为 Docco 的样式组件。然后,我们将 base16Docco 样式作为基本样式,并添加一些自定义样式规则来覆盖其中的颜色。注意到我们在样式定义里使用了 props.theme.colors.secondary 来访问主题中的颜色变量。

最后,我们使用 withTheme 高阶组件将 Highlight 组件包裹起来,以便从主题中获取样式变量。

帮我看看用nextjs服务端 代码: import './topic.scss'; import { okaidia } from 'react-syntax-highlighter/dist/esm/styles/prism'; import ReactMarkdown from 'react-markdown'; import dynamic from 'next/dynamic'; import NoSSR from 'react-no-ssr';

const SyntaxHighlighter = dynamic(() => import('react-syntax-highlighter'), { ssr: false });

function Topic(props: any) { console.log('view topic props:', props); const CodeBlock = ({ language, value }) => { return ( {value} ); };

return ( {props?.topic?.data?.content} {props?.detail?.data.map((p: any, i: number) => { return ( <ReactMarkdown children={p?.content} renderers={{ code: CodeBlock }}> ); })} ); }

export default Topic;

这段代码看起来没有什么问题。您已经正确地使用了next/dynamicNoSSR组件来在Next.js服务端中异步加载react-syntax-highlighter组件,并且在ReactMarkdown组件的renderers属性中将CodeBlock作为自定义渲染器传递了进去。

如果您遇到了其他问题,可以提供更多的细节信息以便我们更好地帮助您解决问题。

  • error node_modules/babel-runtime/helpers/inherits.js (21:10) @ exports.default
  • error Error [TypeError]: Super expression must either be null or a function, not undefined at exports.default (webpack-internal:///(sc_server)/./node_modules/babel-runtime/helpers/inherits.js:16:15) at eval (webpack-internal:///(sc_server)/./node_modules/react-no-ssr/dist/index.js:26:28) at eval (webpack-internal:///(sc_server)/./node_modules/react-no-ssr/dist/index.js:63:2) at Object.(sc_server)/./node_modules/react-no-ssr/dist/index.js (/Users/tercel/source/openai/ai-website/.next/server/app/topic/[id]/page.js:4614:1) at webpack_require (/Users/tercel/source/openai/ai-website/.next/server/webpack-runtime.js:33:42) at eval (webpack-internal:///(sc_server)/./node_modules/react-no-ssr/index.js:2:18) at Object.(sc_server)/./node_modules/react-no-ssr/index.js (/Users/tercel/source/openai/ai-website/.next/server/app/topic/[id]/page.js:4625:1) at webpack_require (/Users/tercel/source/openai/ai-website/.next/server/webpack-runtime.js:33:42) at eval (webpack-internal:///(sc_server)/./views/topic/index.tsx:13:70) at Object.(sc_server)/./views/topic/index.tsx (/Users/tercel/source/openai/ai-website/.next/server/app/topic/[id]/page.js:4903:1) { digest: undefined } null

这个错误可能是由于 babel-runtime 和 react-no-ssr 之间的版本不兼容所导致的。请检查您的 package.json 文件,确保这两个依赖项的版本都匹配。如果仍然存在问题,请尝试升级它们的版本。

此外,您可以尝试使用其他类似的库,如 loadable-components、next/dynamic 等来解决异步加载组件的问题。这些库都提供了一种类似于 react-no-ssr 的方式来在 Next.js 中异步加载组件,但是它们更加稳定和可靠。

如 loadable-components、next/dynamic 等来解决异步加载组件的问题,怎么修改我的代码

好的,下面是如何使用 next/dynamicreact-no-ssr 优化您的代码。

首先,安装必要的依赖项:

npm install next/dynamic react-no-ssr react-syntax-highlighter

接下来,在您的组件中使用 next/dynamicreact-no-ssr 来异步加载 react-syntax-highlighter 组件。下面是示例代码:

import dynamic from 'next/dynamic'
import NoSSR from 'react-no-ssr'

const SyntaxHighlighter = dynamic(
  () => import('react-syntax-highlighter'),
  { ssr: false }
)

function Topic(props: any) {
  console.log('view topic props:', props);

  const CodeBlock = ({ language, value }) => (
    <SyntaxHighlighter language={language} style={okaidia}>
      {value}
    </SyntaxHighlighter>
  )

  return (
    <div className="Topic">
      <div className="TopicLeft">
        <div className="TopicLeftTitle">{props?.topic?.data?.content}</div>
        <div className="TopicLeftContent">
          {props?.detail?.data.map((p: any, i: number) => (
            <NoSSR key={i}>
              <ReactMarkdown children={p?.content} renderers={{ code: CodeBlock }}></ReactMarkdown>
            </NoSSR>
          ))}
        </div>
      </div>
      <div className="TopicRight"></div>
    </div>
  )
}

export default Topic

这里,我们使用 next/dynamic 来异步加载 react-syntax-highlighter 组件,并将 ssr 属性设置为 false,以便在服务器端不会呈现组件。同时,我们使用 react-no-ssr 组件来防止在服务器端呈现高亮显示的代码。

如果您需要自定义样式,请按照 react-syntax-highlighter 的文档创建一个新的样式对象,并将其传递给代码高亮组件的 style 属性。

还是这个错误: - error node_modules/babel-runtime/helpers/inherits.js (21:10) @ exports.default

  • error Error [TypeError]: Super expression must either be null or a function, not undefined at exports.default (webpack-internal:///(sc_server)/./node_modules/babel-runtime/helpers/inherits.js:16:15) at eval (webpack-internal:///(sc_server)/./node_modules/react-no-ssr/dist/index.js:26:28) at eval (webpack-internal:///(sc_server)/./node_modules/react-no-ssr/dist/index.js:63:2) at Object.(sc_server)/./node_modules/react-no-ssr/dist/index.js (/Users/tercel/source/openai/ai-website/.next/server/app/topic/[id]/page.js:4614:1) at webpack_require (/Users/tercel/source/openai/ai-website/.next/server/webpack-runtime.js:33:42) at eval (webpack-internal:///(sc_server)/./node_modules/react-no-ssr/index.js:2:18) at Object.(sc_server)/./node_modules/react-no-ssr/index.js (/Users/tercel/source/openai/ai-website/.next/server/app/topic/[id]/page.js:4625:1) at webpack_require (/Users/tercel/source/openai/ai-website/.next/server/webpack-runtime.js:33:42) at eval (webpack-internal:///(sc_server)/./views/topic/index.tsx:13:70) at Object.(sc_server)/./views/topic/index.tsx (/Users/tercel/source/openai/ai-website/.next/server/app/topic/[id]/page.js:4903:1) { digest: undefined }

这个问题可能是由于 react-no-ssrbabel-runtime 之间的版本不兼容所导致的。您可以尝试升级它们的版本,或者使用其他类似的库,如 loadable-componentsnext/dynamic 来解决在 Next.js 中异步加载组件的问题。

如果您仍然遇到此问题,请查看您的 package.json 文件,并确保将所有依赖项更新为最新版本。您还可以尝试删除 node_modules 目录和 yarn.lockpackage-lock.json 文件,并重新运行 npm installyarn install 命令来重新安装依赖项。

另外,如果您使用了自定义 Babel 配置,可能需要针对这个问题进行调整。请尝试添加以下代码:

{
  "presets": [
    ["next/babel", {
      "transform-runtime": {
        "useESModules": true
      }
    }]
  ]
}

这将启用 Babel 的 transform-runtime 转换,并将其配置为使用 ES 模块语法。

这部分ReactMarkdown 和 SyntaxHighlighter 能否改成直接客服端自动识别格式化呢?

可以使用客户端自动格式化代码的库,例如 Prettier 或 CodeMirror。

Prettier 是一种自动格式化代码的工具,它可以将多种编程语言的代码自动转换为规范的格式。您可以在前端中使用 Prettier,也可以在后端中使用它来生成静态 HTML 页面或动态渲染的 React 组件。

另一个选择是 CodeMirror,它是一个功能强大的文本编辑器组件,可以用于在前端中呈现和编辑代码。CodeMirror 支持高亮显示、缩进和折叠等功能,并且还可以与 Prettier 集成以进行自动格式化。

如果您需要在 Next.js 中使用这些库,需要注意以下几点:

  1. 对于 Prettier,您可以使用 prettierprettier-eslint 包来执行格式化操作。这些包可以在 Node.js 环境下运行,因此您可以在 Next.js 的服务端代码中使用它们。

  2. 对于 CodeMirror,您需要在客户端上使用它。由于 Next.js 是一个 SSR 框架,因此您需要在客户端上动态加载 CodeMirror,以防止在服务器端上呈现该组件。您可以使用 next/dynamicreact-no-ssr 包来异步地加载 CodeMirror 组件。

  3. 如果您的应用程序需要在服务器端呈现代码,则需要在客户端和服务器端之间同步代码的格式。您可以在客户端上使用 Prettier 或 CodeMirror 来格式化代码,并将其与服务器端的代码同步,以确保两者的输出一致。

综上所述,使用客户端自动格式化库需要做出一些调整和妥协。但是,这样可以使您的应用程序更加灵活和可扩展,并且可以提供更好的用户体验。

换成 Prettier 帮我改一下代码

当然可以。以下是使用 Prettier 格式化代码后的示例:

import dynamic from 'next/dynamic';
import NoSSR from 'react-no-ssr';
import { okaidia } from 'react-syntax-highlighter/dist/esm/styles/prism';
import ReactMarkdown from 'react-markdown';

const SyntaxHighlighter = dynamic(() => import('react-syntax-highlighter'), {
  ssr: false,
});

function Topic(props) {
  console.log('view topic props:', props);

  const CodeBlock = ({ language, value }) => {
    return (
      <SyntaxHighlighter language={language} style={okaidia}>
        {value}
      </SyntaxHighlighter>
    );
  };

  return (
    <div className='Topic'>
      <div className='TopicLeft'>
        <div className='TopicLeftTitle'>{props?.topic?.data?.content}</div>
        <div className='TopicLeftContent'>
          {props?.detail?.data.map((p, i) => {
            return (
              <NoSSR key={i}>
                <ReactMarkdown children={p?.content} renderers={{ code: CodeBlock }}></ReactMarkdown>
              </NoSSR>
            );
          })}
        </div>
      </div>
      <div className='TopicRight'></div>
    </div>
  );
}

export default Topic;

注意,Prettier 会根据其默认配置格式化代码,并自动调整缩进、添加空格等。如果您需要更改这些设置,请参阅 Prettier 文档以获取更多信息。