javascript - Syntax Error: Unexpected token < while using renderToString(<RoutingContext {...renderProps} >

I am trying to use React & React-router for server side rendering. So far, it's just a copy pa

I am trying to use React & React-router for server side rendering. So far, it's just a copy paste code from various sources. But I am getting syntax error (Not run-time error) when I try to run the app using node. Below is the code

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

The Error that I get while running node --harmony app.js is

serverHtml: renderToString(<RoutingContext {...renderProps} />)
                                       ^
SyntaxError: Unexpected token <
    at exports.runInThisContext (vm.js:73:16)
    at Module._pile (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

Do I need to install/transform(babelify/jsx) my code for processing the JSX style tags? But I didn't found any such thing stated in any tutorials online.

Resources I followed

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

I am trying to use React & React-router for server side rendering. So far, it's just a copy paste code from various sources. But I am getting syntax error (Not run-time error) when I try to run the app using node. Below is the code

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

The Error that I get while running node --harmony app.js is

serverHtml: renderToString(<RoutingContext {...renderProps} />)
                                       ^
SyntaxError: Unexpected token <
    at exports.runInThisContext (vm.js:73:16)
    at Module._pile (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

Do I need to install/transform(babelify/jsx) my code for processing the JSX style tags? But I didn't found any such thing stated in any tutorials online.

Resources I followed

  1. React-router(Serverside Rendering)
  2. Server Side Rendering by React
Share Improve this question edited Dec 3, 2015 at 19:29 Jigar Jain asked Dec 3, 2015 at 19:00 Jigar JainJigar Jain 1,4472 gold badges15 silver badges38 bronze badges 4
  • Yes, you must transform JSX into standard JS code. JSX is not a ECMAScript standard. – TbWill4321 Commented Dec 3, 2015 at 19:07
  • Are you saying live transpiling this code & running? Like babel-node or something? No tutorials have mentioned this for server side rendering though – Jigar Jain Commented Dec 3, 2015 at 19:09
  • You can use babel-node for development. For production, pile code using a tool before, like react-tools. – TbWill4321 Commented Dec 3, 2015 at 19:12
  • I have added require('node-jsx).install()` but still no effect. I also did add require(babel/register). Taken from following links stackoverflow./questions/31580842/… & stackoverflow./questions/30626410/server-side-rendering-with-react-react-router-and-express?rq=1 – Jigar Jain Commented Dec 3, 2015 at 19:28
Add a ment  | 

2 Answers 2

Reset to default 3

Note - This method is deprecated. There are better alternative out there. As mentioned, require('node-jsx').install() is no longer maintained & using babel is the ideal way to go forward.

So I fixed the issue by making few changes to the above code

I removed the following line as it is not required

require('babel/register');

Then instead of transpiling app.js via babel, I just changed the JSX tag with React.createElement() as below:

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

The full updated code is as below:

'use strict';

const pression    = require('pression');
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(pression());

// 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);
});

Thanks :)

What you are doing will not work because

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

installs a require hook to transpile files that required thenafter.

Also as others have remended, this project is deprecated and using Babel is the best approach now.

You will have to keep your jsx in separate module and require it from your main file.

This is because the JSX file has to be parsed and converted to standard javascript before it reaches the javascript interpreter. In this specific case it is done by intercepting the require method provided by the mon js runtime.

However the file that contains require('babel/register') can not contain JSX syntax because for that registration to occur, the file has to be run by javascript interpreter and for that to happen the file has to be parsed first. This preliminary step will fail because javascript interpreter does not recognize JSX tags.

In addition you will to use the React preset if you are using latest version of Babel.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745195311a4616058.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信