javascript - 使用 eval 动态渲染从后端提供的 JSX
问题描述
我正在开发一个从 python JSON API 获取数据的 React 前端。我网站的一个部分包含优质内容,并为付费用户保留;目前,我通过将内容作为 JSON 对象获取并根据特定约定在前端将其转换为 JSX 来确保其他用户无法访问它。例如:
{
{ 'type': 'paragraph', 'value': 'some text'},
{ 'type': 'anchor', 'href': 'some url', 'value': 'some description'}
}
将呈现为:
<p>some text</p>
<a href="some url">some description</a>
毫不奇怪,随着内容开始变得更有条理,事情开始变得相当复杂,像将部分文本加粗这样简单的事情需要不成比例的努力。
作为一个潜在的解决方案,我有一个想法:与其将内容作为对象发送并解析它,不如发送一个 JSX 字符串并在前端对其进行评估?
我是这样开始的:
import * as babel from "@babel/standalone";
export function renderFromString(code) {
const transformed_code = babel.transform(code, {
plugins: ["transform-react-jsx"]
}).code;
return eval(transformed_code);
}
我在我的高级内容页面中导入了这个函数,并尝试将完整的组件作为字符串传递(使用导入语句等),但由于找不到模块而出现错误。我认为发生这种情况是因为浏览器正在解释代码,因此它无法访问 node_modules?
作为一种解决方法,我尝试仅将标签传递给 renderFromString 并在已导入所有模块的组件的上下文中调用它:
import * as babel from "@babel/standalone";
export function renderFromString(code, context) {
const _es5_code = babel.transform(code, {
plugins: ["transform-react-jsx"]
}).code;
return function() {
return eval(_es5_code);
}.call(context);
}
这也失败了,因为 eval 似乎仍将在本地上下文中运行。
最后,我尝试执行与上述相同的操作,但直接在我的组件中执行 eval,而不是从我的函数中执行。只要我将“React”存储在一个变量中,它就可以工作 : import ReactModule from "react";const React = ReactModule
,否则找不到它。
我的问题是:
- 有什么办法可以使我的前两种方法起作用吗?
- 我知道 eval 被认为是有害的,但由于内容始终是完全静态的并且来自我自己的服务器,所以我不明白这怎么会不安全。我错了吗?
- 我的问题有更好的解决方案吗?也就是说,一种在不更改我的单页应用程序 + JSON api 设置的情况下仅向某些用户安全地交付结构化内容的方法?
解决方案
最好的解决方案是React 服务器端渲染。
由于您需要与客户端兼容但同时通过 React 动态生成的标记,因此您可以将标记生成卸载到服务器。然后,服务器会将呈现的 HTML 发送到客户端以立即显示。
这是一篇关于 React SSR 以及它如何提高性能的好文章。
推荐阅读
- python - 根据可能的配对创建组合
- java - 我想要 JSON 对象的键和值
- swift - 在 Objective-C 中访问嵌套的 Swift 枚举
- vue.js - 使用 rest api 使用 vue js(Nuxt SSR) 创建一个管理面板。它安全吗?
- ios - 如何并行使用 Swift async/await
- bash - Bash 脚本 - 如何让它每 3 秒显示一次状态
- python - 错误找不到 QtWebEngineProcess.exe
- scala - Scala:不规则行为 foldleft() 与 foreach()
- android - 如何在 androidx 抽屉布局小部件中更改字体大小和颜色
- youtube - youtube 中的 yt、ytd、ytd-app 类型的 html 标签是什么?