最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Combining react and jade - Stack Overflow

programmeradmin0浏览0评论

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
  pany-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?

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?

Share Improve this question asked Apr 1, 2015 at 17:13 johnnyutahjohnnyutah 6851 gold badge7 silver badges23 bronze badges 1
  • Its totally fine to render your entire document with Reacts renderToString. There is a penalty on initial page load rendering, although it is very minimal. Considering you are most likely building a SP app, this is really a trivial issue as users only access the initial page build once. – AndrewMcLagan Commented Jun 5, 2016 at 4:05
Add a comment  | 

2 Answers 2

Reset to default 6

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.

发布评论

评论列表(0)

  1. 暂无评论