3

I have an app where I configured server side rendering. Everything is working nice and my component is rendered on the server. The problem is that I get my component rendered twice on the screen. One comes from <div id="content"><%- content %></div>that I am using for server rendering and one comes from <script src="http://localhost:3001/bundle.js"></script>. I use webpack to make two bundles for my server and client. Why is this happening and how can I fix this?

views/index.ejs

<body>
  <div id="app"></div>
  <div id="content"><%- content %></div>
  <script src="http://localhost:3001/bundle.js"></script>
</body>

index.js

app.use(Express.static(path.join(__dirname, '../', 'dist')))

app.use(serverRenderer)
app.get('*', (req: Object, res: Object) => {
  res.render('index', {content: req.body})
})

serverRender

import React from 'react'
import ReactDOM from 'react-dom/server'
import { match, RouterContext } from 'react-router'
import routes from '../client/routes.js'

async function render (component) {
  const content = ReactDOM.renderToString(component)
  return content
}

async function getMatchParams (routes, currentUrl) {
  return new Promise((resolve, reject) => {
    match({routes: routes, location: currentUrl}, (err, redirect, props) => {
      if (err) {
        return reject(err)
      }
      return resolve(props)
    })
  })
}

export default async(req, res, next) => {
  const renderProps = await getMatchParams(routes, req.url)
  if (renderProps) {
    const component = (
      <RouterContext {...renderProps} />
    )
    req.body = await render(component)
    next()
  }
}

2 Answers 2

1

Ok. I have found a problem. I was referring to the bundle and server rendered string with two separate <div>. Inside my app.js I was doing this

render(
    <Router history={browserHistory}>
      {routes}
    </Router>,
  document.getElementById('app')
)

Thats why I should have been sending the string to the template like this.

app.use(Express.static(path.join(__dirname, '../', 'dist')))

app.use(serverRenderer)
app.get('*', (req: Object, res: Object) => {
  res.render('index', {app: req.body})
})

And finally my views/index.js should look like this

<body>
  <div id="app"><%- app %></div>
  <script src="http://localhost:3001/bundle.js"></script>
</body>
Sign up to request clarification or add additional context in comments.

Comments

0

I also faced that problem and found a solution.

On package.json,

"start": "npm-run-all --parallel dev:*",

It will run webpack and node build/bundle.js. Then 2 things happened simultaneously, webpack build project, node build/bundle.js

After webpack built project, then node build/bundle.js runs again since bundle.js is changed.

So there was twice calls on both server and client side. I solved this problem very easily.

First run npm run build, then run node build/bunde.js . Then it will run everything once :)

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.