Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Server-side React: Babel doesn't transform JSX on the server neither on the fly not manually. Why?

I use LoopbackJS framework for Node.js (the same as Express because it is based on Express). And I cannot set React server side rendering. I followed this article, and answers here on Stackoverflow, and other articles, doesn't work.

Babel docs are miserable, no examples, 'try to guess' style. Here is the only piece of info they provide about how to render React on the fly:

$ npm install -g babel-core

require("babel-core/register");

All subsequent files required by node with the extensions .es6, .es, .jsx and .js will be transformed by Babel. The polyfill specified in polyfill is also automatically required.

But it doesn't work.

By the way, other articles suggest to use require("babel/register"). What is the difference? I tried both. Result is the same - SyntaxError: Unexpected token.

Here is my code:

This is client/js/components.js:

var React = require('react');
var ReactDOM = require('react');


var Form = React.createClass({
    render: function() {
        return (
            <form action="" method="post" id="login-form">
                <div><input type="text" id="login" placeholder="Login" /></div>
                <div><input type="text" id="pass" placeholder="Password" /></div>
            <button id="sbm-btn">{login}</button>
        </form>
        );
    }
});

exports.Form = Form;

This is server/boot/routes.js:

require("babel-core/register"); // <== I tried to include it here, doesn't work
var React = require('react');
var ReactDOM = require('react-dom/server');
var components = require('../../client/js/components.js');

module.exports = function(app) {
    app.get('/login', function(req, res) {
        var Form = React.createFactory(components.Form); // <== Include component

        res.render('login', {
            react: ReactDOM.renderToString(Form({login: "Sign In"})) // <== render component
        });
    });
};

This is server/server.js, an enter point. All is standard except that I set up Dust.js as a template engine:

require('babel-core/register'); // <== I tried to include it here. Doesn't work

var loopback = require('loopback');
var boot = require('loopback-boot');
var adaro = require('adaro');  // <== for Dust.js template engine
var path = require('path');
var bodyParser = require('body-parser');

var app = module.exports = loopback();

app.start = function() {
    // start the web server
    return app.listen(function() {
        app.emit('started');
        console.log('Web server listening at: %s', app.get('url'));
    });
};

// Dust.js template engine settings
app.set('views', path.resolve(__dirname, '../views'));
app.engine('dust', adaro.dust({}));
app.set('view engine', 'dust');


// Bootstrap the application, configure models, datasources and middleware.
// Sub-apps like REST API are mounted via boot scripts.
boot(app, __dirname, function(err) {
    if (err) throw err;

    // start the server if `$ node server.js`
    if (require.main === module)
        app.start();
});

And when I try to start a server node server/server.js, I get this long SyntaxError: Unexpected token error throw:

Failed loading boot script: c:\Users\user\sbox\node\myApp\server\boot\routes.js
SyntaxError: c:/Users/user/sbox/node/myApp/client/js/components.js: Unexpected token (8:12)
   6 |     render: function() {
   7 |         return (
>  8 |             <form action="" method="post" id="login-form">
     |             ^
   9 |                 <div><input type="text" id="login" placeholder="Login" /></div>
  10 |                 <div><input type="text" id="pass" placeholder="Password" /></div>
  11 |             <button id="sbm-btn">{login}</button>
    at Parser.pp.raise (c:\Users\user\sbox\node\myApp\node_modules\babel-core\node_modules\babylon\lib\parser\location.js:22:13)
    at Parser.pp.unexpected (c:\Users\user\sbox\node\myApp\node_modules\babel-core\node_modules\babylon\lib\parser\util.js:91:8)
    at Parser.pp.parseExprAtom (c:\Users\user\sbox\node\myApp\node_modules\babel-core\node_modules\babylon\lib\parser\expression.js:510:12)

    at Parser.pp.parseExprSubscripts (c:\Users\user\sbox\node\myApp\node_modules\babel-core\node_modules\babylon\lib\parser\expression.js:2
65:19)
    at Parser.pp.parseMaybeUnary (c:\Users\user\sbox\node\myApp\node_modules\babel-core\node_modules\babylon\lib\parser\expression.js:245:1
9)
    at Parser.pp.parseExprOps (c:\Users\user\sbox\node\myApp\node_modules\babel-core\node_modules\babylon\lib\parser\expression.js:176:19)
    at Parser.pp.parseMaybeConditional (c:\Users\user\sbox\node\myApp\node_modules\babel-core\node_modules\babylon\lib\parser\expression.js
:158:19)
    at Parser.pp.parseMaybeAssign (c:\Users\user\sbox\node\myApp\node_modules\babel-core\node_modules\babylon\lib\parser\expression.js:121:
19)
    at Parser.pp.parseParenAndDistinguishExpression (c:\Users\user\sbox\node\myApp\node_modules\babel-core\node_modules\babylon\lib\parser\
expression.js:583:26)
    at Parser.pp.parseExprAtom (c:\Users\user\sbox\node\myApp\node_modules\babel-core\node_modules\babylon\lib\parser\expression.js:469:19)

c:\Users\user\sbox\node\myApp\node_modules\loopback-boot\lib\executor.js:273
      throw err;
            ^
SyntaxError: c:/Users/user/sbox/node/myApp/client/js/components.js: Unexpected token (8:12)
   6 |     render: function() {
   7 |         return (
>  8 |             <form action="" method="post" id="login-form">
     |             ^
   9 |                 <div><input type="text" id="login" placeholder="Login" /></div>
  10 |                 <div><input type="text" id="pass" placeholder="Password" /></div>
  11 |             <button id="sbm-btn">{login}</button>
    at Parser.pp.raise (c:\Users\user\sbox\node\myApp\node_modules\babel-core\node_modules\babylon\lib\parser\location.js:22:13)
    at Parser.pp.unexpected (c:\Users\user\sbox\node\myApp\node_modules\babel-core\node_modules\babylon\lib\parser\util.js:91:8)
    at Parser.pp.parseExprAtom (c:\Users\user\sbox\node\myApp\node_modules\babel-core\node_modules\babylon\lib\parser\expression.js:510:12)

    at Parser.pp.parseExprSubscripts (c:\Users\user\sbox\node\myApp\node_modules\babel-core\node_modules\babylon\lib\parser\expression.js:2
65:19)
    at Parser.pp.parseMaybeUnary (c:\Users\user\sbox\node\myApp\node_modules\babel-core\node_modules\babylon\lib\parser\expression.js:245:1
9)
    at Parser.pp.parseExprOps (c:\Users\user\sbox\node\myApp\node_modules\babel-core\node_modules\babylon\lib\parser\expression.js:176:19)
    at Parser.pp.parseMaybeConditional (c:\Users\user\sbox\node\myApp\node_modules\babel-core\node_modules\babylon\lib\parser\expression.js
:158:19)
    at Parser.pp.parseMaybeAssign (c:\Users\user\sbox\node\myApp\node_modules\babel-core\node_modules\babylon\lib\parser\expression.js:121:
19)
    at Parser.pp.parseParenAndDistinguishExpression (c:\Users\user\sbox\node\myApp\node_modules\babel-core\node_modules\babylon\lib\parser\
expression.js:583:26)
    at Parser.pp.parseExprAtom (c:\Users\user\sbox\node\myApp\node_modules\babel-core\node_modules\babylon\lib\parser\expression.js:469:19)

What do I do wrong? It it Babel's error or somehow LoopbackJS blocks Babel? How to enable React rendering?

like image 205
Green Avatar asked Nov 21 '15 02:11

Green


1 Answers

According to the Babel.js documentations since version 5:

Out of the box Babel doesn't do anything. In order to actually do anything to your code you need to enable plugins

So you should install appropriate plugin using npm and also pass it to the babel's require hook, something like this:

require('babel-core/register')({
    presets: ['es2015', 'react']
})

Now, install babel-preset-es2015 and babel-preset-react using the following command:

npm install --save babel-preset-es2015 babel-preset-react

In general it should work now but based on your project's structure you may need more changes to make babel work. Feel free to ask any question if my solution does not work.

like image 109
Alireza Ahmadi Avatar answered Nov 09 '22 18:11

Alireza Ahmadi