首页 > 解决方案 > 使用 puppeteer 无头模式在 React SSR 中无法识别函数

问题描述

我正在尝试在一个名为Grid的函数中使用一个调用的 React 自定义组件matrix,一旦matrix执行,它应该挂载GridReactDOMServer. 但window不识别它并引发错误..

我在 puppeteer 无头浏览器中有一个脚本标签,可以将此函数注入 DOM,还有一个 div 元素matrix${index}应该作为注入的地方Grid

puppeteer 配置文件:(为清楚起见,发出代码)

module.exports = async (template, reportData) => {

    ...

    await page.addScriptTag({ path: './src/metrics/matrix.js' });`

    ...

以及matrix要执行的函数:

const React = require('react');
const Grid= React.createFactory(require('../components/Grid'));

----------v // matrix is dimmed in my editor
function matrix(data) {
    const tableConfig = data.resp_example.meta.map((value, i) => ({
        title: (value.name || value.type).toUpperCase(),
        value: value => value[i]
    }));
    const values = data[0] && data[0].values[0];
    const matrix = ReactDOMServer.renderToString(
        <Grid config={tableConfig} data={values.samples[0].y} />
    );
    const matrixId = document.getElementById(`matrix${index}`);
    document.getElementById(`matrix${index}`).style.height = '400px';
    matrixId.innerHTML = matrix;
}

module.exports = matrix;

执行此函数的行如下所示:

window.matrix(data);

该行产生以下错误:

(node:6924) UnhandledPromiseRejectionWarning: Error: Evaluation failed: TypeError: window.matrix is not a function
    at __puppeteer_evaluation_script__:1:346
    at Array.map (<anonymous>)
    at __puppeteer_evaluation_script__:1:70
    at Object.e.w (https://www.amcharts.com/lib/4/core.js:1:94464)
    at __puppeteer_evaluation_script__:1:14
    at ExecutionContext.evaluateHandle (C:\workspace\ReportService\node_modules\puppeteer\lib\ExecutionContext.js:121:13)
    at process._tickCallback (internal/process/next_tick.js:68:7)
  -- ASYNC --
    at ExecutionContext.<anonymous> (C:\workspace\ReportService\node_modules\puppeteer\lib\helper.js:110:27)   
    at ExecutionContext.evaluate (C:\workspace\ReportService\node_modules\puppeteer\lib\ExecutionContext.js:48:31)
    at ExecutionContext.<anonymous> (C:\workspace\ReportService\node_modules\puppeteer\lib\helper.js:111:23)   
    at DOMWorld.evaluate (C:\workspace\ReportService\node_modules\puppeteer\lib\DOMWorld.js:112:20)
    at process._tickCallback (internal/process/next_tick.js:68:7)
  -- ASYNC --
    at Frame.<anonymous> (C:\workspace\ReportService\node_modules\puppeteer\lib\helper.js:110:27)
    at Page.evaluate (C:\workspace\ReportService\node_modules\puppeteer\lib\Page.js:782:43)
    at Page.<anonymous> (C:\workspace\ReportService\node_modules\puppeteer\lib\helper.js:111:23)
    at e (C:\workspace\ReportService\build\server.js:1:6160)
    at e.next (<anonymous>)
    at a (C:\workspace\ReportService\build\server.js:1:4946)
    at s (C:\workspace\ReportService\build\server.js:1:6831)
    at process._tickCallback (internal/process/next_tick.js:68:7)
(node:6924) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:6924) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

看起来一切都应该没问题,函数应该渲染Grid到 DOM 中,有谁知道这里出了什么问题?

提前谢谢大家!

标签: javascriptnode.jspuppeteerserver-side-rendering

解决方案


显然,该错误源于Grid节点内错误使用 ES6 类组件语法,自Grid创建以来createReactClass,即:

const Grid = React.createReactClass({ ... });

解决该问题的选项是:

  1. 配置 webpack babel 转译器来解释 ES6 类:
   npm install --save-dev babel-loader@6.2.1
   npm install --save-dev babel-core@6.4.5
   npm install --save-dev babel-preset-es2015@6.3.13
   npm install --save-dev babel-preset-react@6.3.13```
  1. 利用:const matrix = ReactDOMServer.renderToString( Grid({ config: {tableConfig}, data: {values.samples[0].y} }) );

    代替: const matrix = ReactDOMServer.renderToString( <Grid config={tableConfig} data={values.samples[0].y} /> );

更多信息可以在@React without ES6中找到


推荐阅读