【问题标题】:React: add HTML from generic file path at server-side build timeReact:在服务器端构建时从通用文件路径添加 HTML
【发布时间】:2021-11-23 10:16:52
【问题描述】:
我要实现的用例:
- 管理员在 CMS 中添加 SVG 以及新内容,并在 CMS 中指定哪个 svg 与哪个内容搭配
- CMS 将更改提交到 git (Netlify CMS)
- 静态站点再次构建
- SVG 是内联添加的,因此可以根据它所在的组件设置样式和/或动画
现在 - 我想不出一个干净的方法来添加 SVG 内联。我的逻辑告诉我 - 一切都在构建时可用(svgs 在 repo 中),所以我应该能够简单地内联 svgs。但是我不知道如何根据来自 CMS 内容的变量一般地告诉 React 一个 svg。我可以使用svgr/weback 直接导入 svg,但是我需要在编码时知道文件名,因为它来自 CMS,所以我不需要。我可以使用fs.readFileSync 加载 svg,但是当 react 执行客户端时,SVG 会丢失。
我添加了我当前的解决方案作为答案,但它非常老套。 请告诉我有更好的方法来使用 react!
【问题讨论】:
标签:
node.js
reactjs
next.js
netlify-cms
【解决方案1】:
这是我当前的解决方案,但它在开发模式下随机出现错误,并且似乎与 next.js <Link /> 预取不兼容(我仍然需要调试这个):
我。服务器端渲染
- 从 CMS 数据中读取 SVG 文件路径(Markdown 文件)
- 使用
fs.readFileSync() 加载 SVG
-
Sanitize 和 add React 中的 SVG
二。客户端渲染
- 初始 Get:/URL 响应包含 SVG(ssr 按预期工作)
- 使用
HTMLElement.outerHTML 从 DOM 中读取 SVG
- 当 React 想要渲染它没有的 SVG 时,将 DOM 中的 SVG 传递给它
这里是代码。
import reactParse from "html-react-parser";
import DOMPurify from "isomorphic-dompurify";
import * as fs from "fs";
const svgs = {}; // { urlPath: svgCode }
const createServerSide = (urlPath) => {
let path = "./public" + urlPath;
let svgCode = DOMPurify.sanitize(fs.readFileSync(path));
// add id to find the SVG client-side
// the Unique identifier is the filepath for the svg in the git repository
svgCode = svgCode.replace("<svg", `<svg id="${urlPath}"`);
svgs[urlPath] = svgCode;
};
const readClientSide = (urlPath) => {
let svgElement = document.getElementById(urlPath);
let svgCode = svgElement.outerHTML;
svgs[urlPath] = svgCode;
};
const registerSVG = (urlPath) => {
if (typeof window === "undefined") {
createServerSide(urlPath);
} else {
readClientSide(urlPath);
}
return true;
};
const inlineSVGFromCMS = (urlPath) => {
if (!svgs[urlPath]) {
registerSVG(urlPath);
}
return reactParse(svgs[urlPath]);
};
export default inlineSVGFromCMS;