是否可以使用worker_threads创建异步renderToString?

问题描述 投票:4回答:1

我一直在考虑如何优化反应服务器端渲染,特别是我的应用程序的瓶颈部分,即同步renterToString调用。因为这是一个阻塞调用,所以具有长函数renderToString调用会导致我的应用程序的吞吐量受到相当大的影响。

我碰巧遇到了一个帖子(这里用谷歌翻译从中文翻译成英文),提出假设使用worker_threads卸载renderToString并使其异步。

https://translate.google.com/translate?hl=en&sl=zh-CN&u=https://cnodejs.org/topic/5b2e596557137f22415c4e63&prev=search

我想测试这个功能,似乎有一个阻止因素,因为无法克隆符号,因此无法将符号作为数据传递给工作者:

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,如果是这样,设置渲染器/工作线程的最佳方法是什么。

javascript node.js reactjs react-dom
1个回答
2
投票

我很想知道是否有可能为此目的使用worker_threads,如果是这样,设置渲染器/工作线程的最佳方法是什么。

首先,通常,worker_threads适用于CPU密集型工作(如此),其中并行性和共享内存是有用的。

在这种特殊情况下,简单地旋转多个Node.js进程同样有效。

此外,由于ReactDOMServer渲染速度非常慢 - 您几乎总是必须在React(或Vue或Angular)中将服务器端渲染放在缓存之前。因此,这是一种更容易提高性能的方法。

至于你如何在这里使用worker_threads,它失败了,因为你将组件传递给它。相反,我会将路径或组件名称传递给它,并将require替换为该组件。

或者,您可以自己序列化组件并在另一侧对其进行去病毒化。符号需要唯一性,因此我们不会在Node.js中的工作符之间移动时默认克隆它们。这是你看到的错误。

© www.soinside.com 2019 - 2024. All rights reserved.