语法错误:使用 renderToString(<RoutingContext ...renderProps /> 时出现意外标记 <

Posted

技术标签:

【中文标题】语法错误:使用 renderToString(<RoutingContext ...renderProps /> 时出现意外标记 <【英文标题】:Syntax Error: Unexpected token < while using renderToString(<RoutingContext ...renderProps />语法错误:使用 renderToString(<RoutingContext ...renderProps /> 时出现意外标记 < 【发布时间】:2016-03-08 13:02:14 【问题描述】:

我正在尝试使用 React 和 React-router 进行服务器端渲染。到目前为止,它只是来自各种来源的复制粘贴代码。但是当我尝试使用 node.js 运行应用程序时出现语法错误(不是运行时错误)。下面是代码

App.js

'use strict';
require('babel/register');

const express        = require('express');
const http           = require('http');
const handlebars     = require('express-handlebars');
const renderToString = require('react-dom').server;
const match          = require('react-router').match;
const RoutingContext = require('react-router').RoutingContext;
const Routes         = require('./routes');
const app            = express();
var server;

// JSX transpilation
require('node-jsx').install();

// Setting up handlebars
app.engine('.hbs', handlebars(
    extname: '.hbs',
    layoutsDir: 'views/server',
    partialsDir: 'views/server/partials'
));

app.set('view engine', '.hbs');

// Mount Routes
app.use('*', function (req, res) 
    match(routes: routes, location: req.url, (error, redirectLocation, renderProps) => 
        if (error) 
          res.status(500).send(error.message)
         else if (redirectLocation) 
          res.redirect(302, redirectLocation.pathname + redirectLocation.search)
         else if (renderProps) 
            console.log(renderProps);
            var pageData = 
                serverhtml: renderToString(<RoutingContext ...renderProps />)
            ;
            console.log(pageData);
            res.render('base', pageData);
         else 
          res.status(404).send('Not found')
        
    );
);

server = http.createServer(app);

server.listen('3000', () => 
    console.log('Express server listening on port ' + 3000);
);

我在运行node --harmony app.js 时遇到的错误是

serverHtml: renderToString(<RoutingContext ...renderProps />)
                                       ^
SyntaxError: Unexpected token <
    at exports.runInThisContext (vm.js:73:16)
    at Module._compile (module.js:443:25)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)
    at startup (node.js:129:16)
    at node.js:814:3

我是否需要安装/转换(babelify/jsx)我的代码来处理 JSX 样式标签?但是我在网上的任何教程中都没有发现任何这样的内容。

我关注的资源

    React-router(Serverside Rendering) Server Side Rendering by React

【问题讨论】:

是的,您必须将 JSX 转换为标准的 JS 代码。 JSX 不是 ECMAScript 标准。 你是说实时编译这段代码并运行吗?像babel-node 之类的?虽然没有教程提到过这个用于服务器端渲染 您可以使用babel-node 进行开发。对于生产,使用之前的工具编译代码,例如react-tools 我已经添加了require('node-jsx).install()`,但仍然没有效果。我还添加了require(babel/register)。取自以下链接***.com/questions/31580842/… & ***.com/questions/30626410/server-side-rendering-with-react-react-router-and-express?rq=1 【参考方案1】:

注意 - 此方法已弃用。那里有更好的选择。如前所述,require('node-jsx').install() 不再维护,使用 babel 是前进的理想方式。

所以我通过对上面的代码进行一些更改来解决这个问题

我删除了以下行,因为它不是必需的

require('babel/register');

然后我没有通过 babel 转译 app.js,而是使用 React.createElement() 更改了 JSX 标签,如下所示:

//serverHtml: renderToString(<RoutingContext ...renderProps />)
serverHtml: ReactDOM.renderToString(React.createElement(RoutingContext, renderProps))

完整更新代码如下:

'use strict';

const compression    = require('compression');
const express        = require('express');
const http           = require('http');
const handlebars     = require('express-handlebars');
const path           = require('path');
const React          = require('react');
const ReactDOM       = require('react-dom/server'); // Fixed this
const match          = require('react-router').match;
const RoutingContext = require('react-router').RoutingContext;
const app            = express();
var server;

require('node-jsx').install(); // Not required if you convert the below './routes' file from JSX into js
const Routes = require('./routes');

// Used for Gzipping all the resources
app.use(compression());

// Setting up handlebars
app.engine('.hbs', handlebars(
    extname: '.hbs',
    layoutsDir: 'views/server',
    partialsDir: 'views/server/partials'
));

app.set('view engine', '.hbs');

// Set path to public assets
app.use(express.static(path.join(__dirname, 'public')));

// Mount Routes
app.use('*', function (req, res) 
    match(routes:Routes, location:req.url, (error, redirectLocation, renderProps) => 
        if (error) 
          res.status(500).send(error.message)
         else if (redirectLocation) 
          res.redirect(302, redirectLocation.pathname + redirectLocation.search)
         else if (renderProps) 
            var pageData = 
                serverHtml: ReactDOM.renderToString(React.createElement(RoutingContext, renderProps))
            ;

            res.render('base', pageData);
         else 
          res.status(404).send('Not found')
        
    );
);

server = http.createServer(app);

server.listen('3000', () => 
    console.log('Express server listening on port ' + 3000);
);

谢谢:)

【讨论】:

【参考方案2】:

你正在做的事情不会奏效,因为

require('node-jsx').install();

安装一个 require 钩子来编译之后需要的文件。

正如其他人所推荐的,这个项目已被弃用,现在使用 Babel 是最好的方法。

您必须将您的 jsx 保存在单独的模块中,并从您的主文件中要求它。

这是因为JSX 文件在到达 javascript 解释器之前必须被解析并转换为标准 javascript。在这种特定情况下,它是通过拦截公共 js 运行时提供的require 方法来完成的。

但是,包含require('babel/register') 的文件不能包含 JSX 语法,因为要进行注册,文件必须由 javascript 解释器运行,并且必须首先解析文件。此初步步骤将失败,因为 javascript 解释器无法识别 JSX 标签。

此外,如果您使用的是最新版本的 Babel,您将使用 React preset。

【讨论】:

谢谢。我还是不明白。你是说我必须 babelify app.js?我确实在顶部使用了require('babel/register')。我正在关注这篇文章 ***.com/questions/30626410/server-side-rendering-with-react-react-router-and-expres 我已经用更多解释更新了答案。如果仍然存在一些混乱,请告诉我。 谢谢。我已经解决了这个问题。我使用 React.createElement(RoutingContext, renderProps) 而不是 JSX 标签。这解决了问题:)

以上是关于语法错误:使用 renderToString(<RoutingContext ...renderProps /> 时出现意外标记 <的主要内容,如果未能解决你的问题,请参考以下文章

onClick 处理程序未向 ReactDOMServer.renderToString 注册

angular 2 等效于 react renderToString

React renderToString() 性能和缓存 React 组件

C2061:语法错误:qtypetraits.h 中的标识符“L”

错误:部署云功能时解析触发器出错 - Firebase

第 1 行的 ''')' 附近的 SQL 语法有错误