jedireza / hapi-react-views

:package: A hapi view engine for React components
MIT License
231 stars 33 forks source link

Improving performance through streaming #66

Open tom2strobl opened 7 years ago

tom2strobl commented 7 years ago

This is obviously not an issue, but a possible enhancement: Currently we compile the htmlOutput and then send it over the wire, we could instead leverage streaming the contents down by using https://github.com/FormidableLabs/rapscallion, which imho nailed it.

jedireza commented 7 years ago

Thanks for opening an issue. I'm time poor right now. Though, I'd be interested in what this would/could look like and how we'd integrate (optionally) rapscallion in this module.

tom2strobl commented 7 years ago

Right now I'm experimenting with kind of skipping vision altogether by hooking up reply with reply.renderReact() which (simplified for clarity) looks kinda like this:

renderView.js (+ server.decorate('reply', 'renderReact', require('./lib/renderView.js'));)

module.exports = function(view, dataFromController) {
  const data = extend(someDataWithLocaleOrOtherServerStuff, dataFromController);
  const Component = require(`../components/${view}.js`);
  const componentRenderer = render(<Component {...data} />);
  const responseRenderer = template`
    <html>
      <head>
        [...]
        <div id="app-mount">${componentRenderer}</div>
        [...]
        <script id="app-state">
          window.state = ${() => JSON.stringify(data)}
          document.querySelector("#app-mount").setAttribute("data-react-checksum", "${componentRenderer.checksum()}")
        </script>
        <script src="/scripts/client.js"></script>
      </body>
    </html>
  `;
  const stream = responseRenderer.toStream();
  this(stream);
}

someController.js

reply.renderReact('home', {
  title: 'Home',
  records: someDatabaseResult,
});

Which feels wrong but works surprisingly well.

wswoodruff commented 7 years ago

@tom2strobl I'd love for vision to have a great solution for server-side React rendering (like this lib here!) -- what would be your ideal interface as far as passing options? Would anything else drive your decision besides streaming?

jedireza commented 6 years ago

React v16 supports streaming:

Even though streaming isn't totally general purpose (there are some gotchas), I'm much more inclined to try incorporating a streaming API in hapi-react-views now that's it's officially part of React.

Is rapscallion still needed?

tom2strobl commented 6 years ago

@wswoodruff to be honest we moved away from hapi directly serving client markup at all. We run next.js and it's getInitialProps in the front and regular hapi in the back (and merged the next-handler into hapi to have one single clean server) and all data APIs and client templates are separated. Vision does both at the same time, gathering data and then rendering markup from a template. The age of code splitting, lazy loading and prefetching made things a little more complex…

wswoodruff commented 6 years ago

@tom2strobl Cool! I haven't delved too much into SSR for React yet, seems like a great setup!