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:
body .company-logo.center #react-main-mount != reactOutput include ./content_block_1.jade include ./content_block_2.jade #slideshow-main-mount != 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?
You can definitely use Node JS with React framework. In fact, Node JS is known to be the most suitable platform for hosting and running web servers for applications built on React. The two primary reasons for this are; Node uses a node package manager or an NPM to install all new updates and packages.
Our jQuery app initially creates the React component using a call to React. createElement and passing in the context of the jQuery app to the components constructor. The component can then store the reference (available via the props argument) in its state and use it to update key elements on the web page.
By default, React does not permit you to inject HTML in a component, for various reasons including cross-site scripting. However, for some cases like a CMS or WYSIWYG editor, you have to deal with raw HTML.
With React, we write HTML using JavaScript. We rely on the power of JavaScript to generate HTML that depends on some data, rather than enhancing HTML to make it work with that data. Enhancing HTML is what other JavaScript frameworks usually do.
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.
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 render(){ return ( <html> <head> // etc. </head> <body> <div id="app" dangerouslySetInnerHTML={{__html: this.props.markup}}> </div> </body> <script dangerouslySetInnerHTML={{__html: this.props.state}</script> <script> // GA Scripts etc. </script> </html> ) }
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 https://github.com/yahoo/flux-examples/tree/master/react-router 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.
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: https://github.com/jadejs/react-jade.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With