【问题标题】:SSR with React : Unexpected token '<' in call to renderToString()带有 React 的 SSR:调用 renderToString() 时出现意外的令牌“<”
【发布时间】:2021-10-13 10:16:40
【问题描述】:

我正在使用 react 处理 SSR,但遇到以下错误。
语法错误:意外令牌'

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

如上所述是here

babel-register 不处理调用它的文件。

因此,我在一个新文件中正确地声明了我的 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有关系,请帮忙

【问题讨论】:

    标签: javascript node.js reactjs babeljs server-side-rendering


    【解决方案1】:

    我认为有两件事需要改变。在您的 initialControler.js 上,您在 node.js 文件中使用导出默认值,使用 module.exports module.exports vs. export default in Node.js and ES6

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

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

    module.exports 和 require 为 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)
    
    

    【讨论】:

    • 您好,感谢您的回复。最新版本的节点确实支持es module syntax。我已经接受了另一个答案。感谢您的时间。 :)
    【解决方案2】:

    在您的 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 钩子会将自己绑定到节点的 require 并在 runtime 自动编译文件。如果您删除 type: "module",使用 es 模块的 server.js 不会发生冲突。 require 的顺序很重要,我们需要在 index.js 中使用 babel-register 以及识别 then-required server.js 中的语法所需的预设。

    【讨论】:

    • 您好,感谢您的回复。如前所述,我对index.js 文件进行了更改并将其转换为require 语法。它有效,但现在样式不会从服务器呈现。另外,您能告诉我为什么您将index.js 文件转换为require 语法,以及考虑到我在package.json 文件中添加type : "module",为什么不考虑ES module 语法工作。还有一件事是在index.js 文件中,require('./server') 在最后一行,server.js 使用es module 语法进行导入/导出不会与@中的require 语法冲突 987654346@文件。
    • 我已经用解释更新了答案。
    • 我了解 babel 预设如何识别 server.js 文件中的语法,因此这不会与 index.js 文件中的 require 语法冲突,谢谢为了清除这个。但是,写入type : "module" 允许我们在节点文件中使用es module syntax。那么我们不能让我们的index.js 使用es module syntax 吗? index.js中的那些require语法,能不能改成es module语法?
    • 感谢@deechris27 的帮助 :)
    • 当我尝试调试此问题 (stackoverflow.com/a/68210160/8370370) 时,我发现了这个“类型:模块”的问题。我已经编辑了答案的那一部分,以免混淆:)。我实际上是说将 require 与 type:module 一起使用会引发错误。谢谢
    【解决方案3】:

    兄弟们不要浪费时间阅读他们的羊皮纸。 您需要做的就是删除任何空格 b4 和每个 &gt;&lt;

    
    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>`);
    
    

    【讨论】:

    • 您好,感谢您的回复。现在这个问题已经解决了。感谢您的时间。 :)
    • 别忘了点赞,这样可以帮助到别人
    猜你喜欢
    • 1970-01-01
    • 2020-05-31
    • 2022-06-12
    • 2017-06-22
    • 2020-12-23
    • 2019-01-28
    • 2013-03-22
    • 1970-01-01
    • 2021-06-22
    相关资源
    最近更新 更多