如何在Strapi中存储TypeScript代码片段并在SSG NextJS中调用?
解决Strapi存储TS代码片段在NextJS中渲染的跨脚本问题
一、Strapi端优化存储方式
- 别用普通字符串字段存代码,改用Markdown字段(Strapi插件市场有官方Markdown插件),存的时候把代码放在代码块里(用
ts ...包裹),这样Strapi返回的是标准Markdown格式内容,自带代码块标记。 - 如果坚持用字符串字段,在Strapi的
beforeSave生命周期钩子中自动转义代码里的特殊HTML字符:把<转成<,>转成>,&转成&,避免代码被浏览器识别为HTML/脚本标签。
二、NextJS端安全渲染代码片段
- 用专业的代码高亮组件,比如
react-syntax-highlighter:- 安装依赖:
npm install react-syntax-highlighter - 在组件中导入并使用:
这种方式会把代码字符串转成安全的DOM元素,完全避免跨脚本风险,还自带语法高亮。import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; import { tomorrow } from 'react-syntax-highlighter/dist/esm/styles/prism'; export default function CodeBlock({ code }) { return ( <SyntaxHighlighter language="typescript" style={tomorrow}> {code} </SyntaxHighlighter> ); }
- 安装依赖:
- 如果用Markdown字段存储,NextJS里用
react-markdown解析,配合代码块处理插件:import ReactMarkdown from 'react-markdown'; import remarkGfm from 'remark-gfm'; import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; import { tomorrow } from 'react-syntax-highlighter/dist/esm/styles/prism'; export default function MarkdownRenderer({ content }) { return ( <ReactMarkdown remarkPlugins={[remarkGfm]} components={{ code({ node, inline, className, children, ...props }) { const match = /language-(\w+)/.exec(className || ''); return !inline && match ? ( <SyntaxHighlighter language={match[1]} style={tomorrow} {...props} > {String(children).replace(/\n$/, '')} </SyntaxHighlighter> ) : ( <code className={className} {...props}> {children} </code> ); }, }} > {content} </ReactMarkdown> ); } - 绝对禁止直接用
dangerouslySetInnerHTML渲染未处理的代码字符串,这是跨脚本风险的根源。
三、额外技巧
- 如果代码片段来自GitHub仓库,可以在Strapi里存储GitHub的文件路径/API链接,然后在NextJS中通过SWR或React Query异步拉取代码内容,不用在Strapi里存大段代码,还能保持代码和仓库同步。拉取后用上面的组件渲染即可,注意处理私有仓库的权限(用GitHub Personal Access Token)。
内容的提问来源于stack exchange,提问作者Nobby_Nobody
相关产品推荐
相关产品推荐

