语法错误:意外的令牌&lt;使用renderToString时(<routingcontext {... renderprops} =“”>

时间:2015-12-03 19:00:51

标签: javascript node.js reactjs react-router

我正在尝试使用React&amp;用于服务器端渲染的React-router。到目前为止,它只是来自各种来源的复制粘贴代码。但是当我尝试使用节点运行应用程序时,我收到语法错误(非运行时错误)。以下是代码

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样式标记?但我没有在网上任何教程中找到任何这样的内容。

我遵循的资源

  1. React-router(Serverside Rendering)
  2. Server Side Rendering by React

2 个答案:

答案 0 :(得分:2)

注意 - 不推荐使用此方法。那里有更好的选择。如上所述,require('node-jsx').install()已不再保持&amp;使用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);
});

谢谢:)

答案 1 :(得分:1)

你正在做什么是行不通的,因为

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

安装一个require钩子来转换后来需要的文件。

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

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

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

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

此外,如果您使用的是最新版本的Babel,则可以使用React preset