带有 React 的 SSR:调用 renderToString() 时意外的标记“<”

SSR with React : Unexpected token '<' in call to renderToString()

我正在使用 React 处理 SSR,但遇到以下错误。
语法错误:意外标记“<”`

 <div id="root">${ReactDOMServer.renderToString(<App />)}</div>```
                                                ^

提到的是

babel-register doesn't process the file it is called from.

因此,我正确地在一个新文件中声明了我的 babel 依赖项,但是我仍然遇到上述错误。

下面是我的index.js文件

import babelRegister from '@babel/register';
import ignoreStyles from 'ignore-styles';

babelRegister({
  ignore: [/node_modules/],
  presets: ['@babel/preset-env', '@babel/preset-react'],
});

import express from 'express';
import appRender from './server.js';

const app = express();
appRender(app);

我的 server.js 文件。

import initialRenderRoutes from './routes/initialRenderRoutes.js';
import path from 'path';

const appRender = (app) => {
  const __dirname = path.resolve();

  app.use(express.static(path.resolve(__dirname, '../build')));

  app.use('*', initialRenderRoutes);

  const port = 5000;

  app.listen(port, () => console.log(`Server running on port ${port}`));
};
export default appRender;

我的initialController.js文件

import fs from 'fs';
import ReactDOMServer from 'react-dom/server.js';
import path from 'path';

import App from '../../src/App.js';

const initialRenderController = (req, res, next) => {
  console.log(path.resolve());
  fs.readFile(
    path.resolve('../client/build/index.html'),
    'utf8',
    (err, data) => {
      if (err) {
        console.log(err);
        return res.status(500).send('Internal Server Error');
      }
      return res.send(
        data.replace(
          '<div id="root"></div>',
          `<div id="root">${ReactDOMServer.renderToString(<App />)}</div>`
              <<<<The problem lies here>>>>
        )
      );
    }
  );
};

export default initialRenderController;

是不是和babel有关的东西,求助

我认为有两件事需要改变。一个在你的 initialControler.js 上,你在 node.js 文件中使用导出默认值,使用 module.exports

您应该更改节点文件中的所有导入。

你在 React 中使用 export / export default 然后 import 拉入文件 https://www.geeksforgeeks.org/reactjs-importing-exporting/

module.exports 并要求为 Node 拉入文件 What is the purpose of Node.js module.exports and how do you use it?

其次,他们将 app.get 移动到那个 renderReact.js 文件中,然后要求它进入他们的 index.js 文件。但是,在您的 server.js 文件中,我没有看到您在 initialController 文件中导入。

从你的例子来看,你应该这样做:

Server.js


let initialController = require('/path to this file');
initialController(app)

尝试在您的 index.js 文件中进行以下更改,

require('ignore-styles');

require('@babel/register')({
    ignore: [/(node_modules)/],
    presets: ['@babel/preset-env', '@babel/preset-react']
});

require('./server');
require('./initialController');

上面的应该可以,我在本地测试了下面的,它工作得很好。

我的server.js

import express from 'express';
import fs from 'fs';
import path from 'path';

import React from 'react';
import ReactDOMServer from 'react-dom/server';

import App from '../App';

const app = express();

app.use('^/$', (req, res, next) => {

    fs.readFile(path.resolve('./build/index.html'), 'utf-8', (err, data) => {
        if (err) {
            console.log(err);
            return res.status(500).send("Some error occurred")
        }
        return res.send(data.replace('<div id="root"></div>', `<div id="root">${ReactDOMServer.renderToString(<App />)}</div>`))
    })
});

app.use(express.static(path.resolve(__dirname, "..", "build")));

app.listen(5000, ()=>{
    console.log("App running on port 5k")
})

index.js

require('ignore-styles');

require('@babel/register')({
    ignore: [/(node_modules)/],
    presets: ['@babel/preset-env', '@babel/preset-react']
});

require('./server');

希望您拥有包含所需预设的 .babelrc 文件。

更新回复评论:

考虑删除 type: "module",因为当您使用 require 时会抛出错误。 @babel/register 将 运行 文件在 fly 上使用 babel。 require hook 将自身绑定到节点的 require 并会在 运行time 自动编译文件。 server.js 如果删除 type: "module",使用 es 模块不会发生冲突。 require 的顺序很重要,我们需要在 index.js 中使用 babel-register 来识别 then-required server.js 中的语法。

兄弟,别浪费时间看羊皮纸了。 您需要做的就是删除任何 space b4 并在每个 ><

之后

const val= ReactDOMServer.renderToString(<App />);

/// make sure you don’t have any sort of space 
/// between them > < and yow ${}
/// is better if you store that long  text into an small var, as I did to ///prevent prettier or some other  to add a line break of an space

return res.send( `<div id="root">${val}</div>`);