Combining react and jade

I am working on an isomorphic javascript app with express + react. We started out using jade for server side templates for static content, but combining the two is quickly becoming unwieldy. We have ended up with something like this:

In the express routes:

router.get("", function(req, res) {
  var webpackStats = require('../../config/webpack-stats.json');
  var reactHtml = React.renderToString(HiwApp({}));
  var slideshowHtml = React.renderToString(slideshowApp({}));
  var config = {
    webpackStats: webpackStats,
    reactOutput: reactHtml,
    slideshowHtml: slideshowHtml
  res.render("how_it_works/howitworks", config);

In Jade:

    != reactOutput
  include ./content_block_1.jade

  include ./content_block_2.jade

    != slideshowHtml

This is very brittle-if we want jsx then a jade template then more jsx, we have to make sure we get the order right.

My idea is to do it all with jsx. I know there is React.renderToStaticMarkup for this sort of thing, but that doesn’t solve the problem of mixing dynamic with static pages.

The big questions: if we decide to do all of this with jsx (say layout.jsx which contains all components), then call React.renderToString(App({});, will this be a major performance hit? If so, is there a better way to do it to easily combine static and dynamic blocks?

Although this may be a tiny bit off topic: We stuck with jade templates.

Basically we wanted the flexibility to use a non-react + flux architecture for areas of the site when and if that need arose. Our site is basically made up of a number of smaller SP apps: Site, UserAccount, Team and Admin.

Why did we do this?

  • Smaller filesize and overhead for users who are not accessing all sections of the site.

  • Option to “opt out” of React and flux if and when the need arises.

  • Simpler, server side authentication.

Read More:   Toggle visibility property of div

The way we have done it successfully was to render a JSX shell template (Html.jsx) on the server using React.renderToStaticMarkup() and then send it as the response to every server-side express route request that is meant to deliver some HTML to the browser. Html.jsx is just a shell containing html head information and GA scripts etc. It should contain no layout.

// Html.jsx
  return (
        // etc.
          dangerouslySetInnerHTML={{__html: this.props.markup}}>
      <script dangerouslySetInnerHTML={{__html: this.props.state}</script>
        // GA Scripts etc.

Remember it is totally fine and even recommended to use dangerouslySetInnerHTML on the server when hydrating your app.

Dynamic layout should be done with your your isomorphic components through a hierarchy of components based on their state/props configuration. If you happen to be using React Router, then your router will render view handlers based on the routes you provide it so that means you don’t need to manage that yourself.

The reason we use this technique is to architecturally separate our “App” which is isomorphic and responds to state from our server-side template shell which is just a delivery mechanism and is effectively boiler plate. We even keep the Html.jsx template amongst all the express components within our app and do not let it mix with the other isomorphic React components.

One of the most helpful resources I found for working out React/isomorphic architecture was which is where we stole this technique from.

We explored the idea of integrating handlebars as a templating engine for client’s devs using our products in the future but decided that it was less complex to write our own DSL in JSX and use some simple parsing routines to parse our HTML-like DSL to JSX by adding things like export default (ES6 module syntax) at the start of the template and then import the template to a rendering component.

Read More:   Disable form auto submit on button click

You could of course follow that line of thought and use a jade compiler to spit out the template and then add module syntax around that if you think separate jade files are essential. I also noticed this project as well although I have not explored it in anger:

The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .

Similar Posts