是否可以使用worker_threads进行异步renderToString?

时间:2019-04-25 17:39:52

标签: javascript node.js reactjs react-dom

我一直在考虑如何优化React Server端渲染,尤其是我应用程序的瓶颈部分,这是同步的RenterToString调用。因为这是一个阻塞调用,所以具有长函数renderToString的调用会导致我的应用程序的吞吐量遭受相当大的损失。

我碰巧遇到了一个线程(这里是用Google翻译将其从中文翻译成英文),提出了一个假设,可以使用worker_threads卸载renderToString并使它异步。

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

我想测试此功能,并且似乎存在一个阻止程序,因为无法克隆Symbol不能将其作为数据传递给worker:

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

1 个答案:

答案 0 :(得分:2)

  

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

首先,一般来说worker_threads适用于CPU密集型工作(像这样),在这些工作中并行性和共享内存是有帮助的。

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

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

关于在这里如何使用worker_threads,它失败了,因为您将组件传递给了它。取而代之的是,我将路由或组件名称传递给它,并使其require成为该组件。

或者,您可以自己序列化组件,然后在另一端进行反序列化。符号需要唯一性,因此在Node.js中的工作人员之间移动内容时,默认情况下不会克隆它们。这是您看到的错误。