1

We want to build a production-ready social network website (Facebook or Instagram style). We plan to use Node on the server side and are looking for the best technology for rendering view components on the server side.

SEO friendliness is a must, so Angular doesn’t seem like a good fit (unless anyone can advocate for Prerender.io as a solid choice).

We also wish to support AJAX so that most of the rendering would be done on the server, but updates would be done on the client.

Having looked at React, it seems like a good choice, but there’s one thing I’m worried about - the fact that out of the box, you would need to load all data at the route level as opposed to the component level (since renderToString is synchronous - see the discussion here

I don't really understand what would be a robust alternative for server side rendering if we're passing on React.

If I understnd correctly, the basic way (which does allow async loading from within sub components) would be something like:

  // The main page route
app.get('/',function(){
  var html = renderBase();
  renderHeader(html)
    .then(
    renderFeed(html)
  ).then(
    renderFooter(html)
  );
})

renderBase = function(){
  return = "<html><body>..."
}

renderHeader = function(){

  someIoFunction(function(){

    // build HTML based on data

  })

}

Seemingly using a template engine such as Jade might relieve us of some of the burden, but I can't seem to find anything on this "React vs. Templating engine" so-called issue, so probably I'm not seeing it correctly.

Thanks.

Community
  • 1
  • 1
Shahar
  • 478
  • 5
  • 17
  • On the server you've always needed to load all of the data upfront. I haven't seen any good alternatives to this anywhere (without sacrificing load time, of course). – Brigand Jul 07 '15 at 05:00
  • I've added a pseudo code example of what I mean above. I think it does allow to load data from within sub components. – Shahar Jul 07 '15 at 05:22
  • Google's crawler [executes javascript](http://googlewebmastercentral.blogspot.no/2014/05/understanding-web-pages-better.html) these days. Which other crawlers are a problem for you? – Jorg Jul 07 '15 at 05:28
  • You have the same problem with templates, btw. Aside from the stuff that happens on the client after mount, react is little more than a template system, and nothing less. – Brigand Jul 07 '15 at 06:11
  • If each component defines it’s own data dependency, you can call `React.renderToStaticMarkup` using your top level app in your node route to collect all data dependencies before calling `React.renderToString` and render the results backend. – David Hellsing Jul 07 '15 at 07:34
  • @Jorg see the [link](https://scotch.io/tutorials/build-a-real-time-twitter-stream-with-node-and-react-js) for why I'm worried about crawling. From the documentation I don't see how that helps.. wouldn't I have to provide renderToStaticMarkup with all the fetched data? Similar to renderToString, except this doesn't create extra DOM attributes such as data-react-id, that React uses internally. This is useful if you want to use React as a simple static page generator, as stripping away the extra attributes can save lots of bytes. – Shahar Jul 07 '15 at 08:15
  • @Shahar this was more directed at your comment about not using angular for that reason. – Jorg Jul 07 '15 at 08:16
  • I can see why I got you confused. The link I've added in the comment talks briefly about why not to use Angular – Shahar Jul 07 '15 at 09:49
  • @Shahar I see, thanks for clarifying – Jorg Jul 07 '15 at 22:52

1 Answers1

1

Basically the solutions come down to using a convention where each component has a static function which returns the data it needs, and it calls the function of the same name on the components it needs. This is roughly how it looks:

class CommentList {
  static getData = (props) => {
    return {
      comments: api.getComments({page: props.page})
    };
  }
}

class CommentApp {
  static getData = (props) => {
    return {
      user: api.getUser(),
      stuff: CommentList.getData({page: props.commentPage})
    };
  }
  render(){
    return <CommentList comments={this.props.stuff.comments} />
  }
}

Or you can figure out all of the data requirements at the top of the tree, but while simpler to start out, it's more fragile. This is what you do with templates.

Brigand
  • 84,529
  • 20
  • 165
  • 173