3

I'm working on SSR with react but I'm encountering the following error.
Syntax error: Unexpected token '<'`

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

As mentioned is here

babel-register doesn't process the file it is called from.

Therefore, I rightly declared my babel dependencies in a new file, however I'm still getting the above error.

Below is my index.js file

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

My server.js file.

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;

My initialController.js file

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;

Is it something related to babel, please help.

Tarun Singh
  • 430
  • 8
  • 18

3 Answers3

1

Try the below changes in your index.js file,

require('ignore-styles');

require('@babel/register')({
    ignore: [/(node_modules)/],
    presets: ['@babel/preset-env', '@babel/preset-react']
});

require('./server');
require('./initialController');

The above should work, I tested locally the below, it works perfectly fine.

My 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');

I hope you have the .babelrc file with the required presets.

Update in response to comment:

Consider removing type: "module", since it will throw error when you use require. @babel/register will run files using babel on the fly. The require hook will bind itself to the node’s require and will automatically compile files at runtime. server.js using es module won't clash if you remove type: "module". The order of require matters, we require babel-register in index.js with the presets needed to recognize the syntaxes in the then-required server.js.

dee
  • 2,244
  • 3
  • 13
  • 33
  • Hi, Thank you for your response. As mentioned I made changes to my `index.js` file and converted it to `require` syntax. It worked but now the styles do not get rendered from the server. Also, can you tell me why you shifted to a `require` syntax for `index.js` file and why not `ES module` syntax work considered that I'm adding `type : "module"` in my `package.json` file. One more thing is in `index.js` file with `require('./server')` at the last line, the `server.js` uses `es module` syntax for importing/exporting won't it **clash** with `require` syntax in `index.js` file. – Tarun Singh Aug 10 '21 at 12:54
  • I've updated the answer with an explanation. – dee Aug 10 '21 at 13:25
  • I understood how babel presets would recognize syntax in the `server.js` file and therefore this won't **clash** with the `require` syntax in `index.js` file, thank you for clearing this out. However, writing `type : "module"` allows us to use `es module syntax` in our node files. So can't we make our `index.js` to use `es module syntax`? Those `require` syntax in `index.js`, can we change it to `es module` syntax? – Tarun Singh Aug 10 '21 at 13:41
  • Yes, I understand, I suggested require bcoz I don't know the version of node you have in system, I believe it'll only work for node above version 12. it's safer to recommend require since it will work for everyone unless they've "type":"module" or .mjs files. Yes, you can try with es-modules in index.js, personally, I haven't tried so far. – dee Aug 10 '21 at 13:48
  • @TarunSingh if my answer helped with your issue, please consider accepting, upvoting. Thanks – dee Aug 10 '21 at 13:53
  • Okay got it, also can you please edit your answer as it mentions that removing `type: module` will throw an error when using `require` syntax, I think it's the other way round. If you put `type:module` then it'll throw an error saying `require` is not defined. So if we're using `require` syntax then we don't need to add `type: module` in our `package.json` file. – Tarun Singh Aug 10 '21 at 13:58
  • 1
    I'd figured out the issue with this "type:module" while I tried to debug for this issue (https://stackoverflow.com/a/68210160/8370370) sometime back. I've edited that part of answer so that It's not confusing :). I actually meant to say using require with type:module will throw error. Thanks – dee Aug 10 '21 at 14:18
0

I believe there are two things that need to be changed. One on your initialControler.js you are using export default in a node.js file, use module.exports module.exports vs. export default in Node.js and ES6

You should change all the imports in your node files.

You use export / export default in React and then import to pull in the files https://www.geeksforgeeks.org/reactjs-importing-exporting/

module.exports and require to pull in the files for Node What is the purpose of Node.js module.exports and how do you use it?

Second they moved the app.get into that renderReact.js file and then required it into their index.js file. However on your server.js file I don't see you importing in your initialController file.

From your example it looks like you should be doing something like this:

Server.js


let initialController = require('/path to this file');
initialController(app)

Dan
  • 361
  • 1
  • 5
  • 17
  • Hi, thanks for your response. The latest version of node does support `es module syntax`. I've accepted the other answer. Thank you for your time. :) – Tarun Singh Aug 10 '21 at 14:22
0

Yow broh don’t waste yow time reading them parchments. All you need to do is remove any space b4 and after each ><


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

Ernesto
  • 3,944
  • 1
  • 14
  • 29