1

I have been struggling with a seemingly simple issue. I was working on setting up a new React Project and structuring my folder. I had something like this:

/node_modules
/public
   |__ 0.bundle.js
   |__ bundle.js
   // the goal is to move index.html in this folder
/src
   |__components
   App.js
   ClientApp.js
.babelrc
.eslintrc
index.html
package.json
server.js
webpack.config.js
yarn.lock

Now my index file looks simply like this:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>React Test</title>
</head>
<body>
  <div id="app"><%= body %></div>
  <script src="/public/bundle.js"></script>
</body>
</html>

And my server.js is:

require('babel-register')

const express = require('express')
const React = require('react')
const ReactDOMServer = require('react-dom/server')
const ReactRouter = require('react-router-dom')
const StaticRouter = ReactRouter.StaticRouter
const _ = require('lodash')
const fs = require('fs')
const PORT = 5000
const baseTemplate = fs.readFileSync('./index.html')
const template = _.template(baseTemplate)
const App = require('./src/App').default

const server = express()

server.use('/public', express.static('./public'))

server.use((req, res) => {
  const body = ReactDOMServer.renderToString(
    React.createElement(StaticRouter, {location: req.url, context: {}},
      React.createElement(App)
    )
  )

  res.write(template({body: body}))
  res.end()
})

console.log('listening on port', PORT)
server.listen(PORT)

And everything works like a charm (both server and client rendering), now I wanted to make a simple change and move the index.html file inside the /public folder. I did it updating the respective files that were pointing to it as well as where index is looking for the bundle.js. file. So my new index.html is:

...
<body>
  <div id="app"><%= body %></div>
  <!-- <script src="/public/bundle.js"></script> I actually removed this -->
  <script src="bundle.js"></script>
</body>
...

And my server is updated to:

...
const baseTemplate = fs.readFileSync('./public/index.html')
const template = _.template(baseTemplate)
const App = require('./src/App').default

...
server.listen(PORT)

With this setup client rendering still works but server side rendering throws an error:

Uncaught SyntaxError: Unexpected token <

It took me a while to pinpoint the issue. and apparently the server.js is capable of detecting the file after I move it to the public folder (if I inspect the HTML it is in fact there), but it has troubles loading the actual app (meaning the js). I feel like making this change broke some references that I am now giving for granted. Any thought on where to look for my mistake ?

1 Answer 1

2

Funny enough I found out what the problem was, my configuration had issues that involved webpack as well, that I was skipping over. I did not update the output path according to my new configuration.

output: {
  path: path.join(__dirname, '/public'),
  filename: 'bundle.js',
  // publicPath: '/public/' --> This was causing the error
  publicPath: '/js/'
},

The reason why that was causing the error is due to the fact that if index.html is placed in the main folder (as it was originally) then it needs to look for the bundles inside the public folder as the old webpack config specified with publicPath. After moving the index.html inside the public folder, the bundles would now be in the same folder as the index.html file so the path we should refer to is now index own folder. This translates into the new publicPath specified in the snippet above.

I hope this can help others, I should have been more aware of my webpack config and I would have not ran into this issue. Happy coding!

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.