我一直在思考如何优化 React 服务器端渲染,尤其是我应用程序中的瓶颈部分,即同步 renterToString 调用。因为这是一个阻塞调用,所以长函数 renderToString 调用会导致我的应用程序的吞吐量受到相当大的影响。
我碰巧看到一个线程(这里用谷歌翻译从中文翻译成英文)提出了一个假设使用 worker_threads卸载 renderToString 并使其异步。
我想测试这个功能,似乎有一个障碍,因为 Symbol 不能作为数据传递给工作人员,因为它不能被克隆:
DataCloneError: Symbol(react.element) could not be cloned.
以下是设置工作线程/服务器渲染逻辑的示例代码:
// asyncRenderer.js
const { Worker, isMainThread, parentPort, workerData } = require('worker_threads');
if (isMainThread) {
module.exports = async function asyncRenderToString(component) {
return new Promise((resolve, reject) => {
const worker = new Worker(__filename, {
workerData: component,
});
worker.on('message', resolve);
worker.on('error', reject);
worker.on('exit', (code) => {
if (code !== 0) {
reject(new Error(`Worker stopped with exit code ${code}`));
}
});
});
};
} else {
const { renderToString } = require('react-dom/server');
const HTML = renderToString(workerData);
parentPort.postMessage(HTML);
}
// server.jsx
const asyncRenderer = require('./asyncRenderer');
...
const html = await renderToString(<App/>);
// Return the html
我很想知道是否可以为此目的使用 worker_threads,如果可以,设置渲染器/工作线程的最佳方法是什么。
最佳答案
I'd love to hear if it is possible to use worker_threads for this purpose, and if so, what the best approach for setting up the renderer/worker threads would be.
首先,一般来说,worker_threads 适用于 CPU 密集型工作(像这样),其中并行性和共享内存很有帮助。
在这种特殊情况下,简单地旋转多个 Node.js 进程同样有效。
此外,由于 ReactDOMServer 渲染速度非常慢 - 在 React(或 Vue 或 Angular)中,您几乎总是必须在服务器端渲染之前放置一个缓存。因此,这是一种更容易提高性能的方法。
至于如何在这里使用 worker_threads,它会失败,因为您将组件传递给它。相反,我会将路由或组件名称传递给它,并让它 require
该组件。
或者,您可以自己序列化组件并在另一端反序列化。符号需要唯一性,因此在 Node.js 中的工作人员之间移动事物时,默认情况下我们不会克隆它们。这是您看到的错误。
关于javascript - 是否可以使用 worker_threads 制作异步 renderToString?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55854890/