apps: If we want to optimize for the best possible user experience and performance, giving up one or the other is never a good idea.” - Guillermo Rauch http://rauchg.com/2014/7-principles-of-rich-web-applications/
YUI on the server and the client Lessons learned: • Browser abstractions are too slow for the server • Synchronizing server, client, and DOM was hard • Using YUI’s module format was problematic in node.js
mixing formats ▪ Use polyfills instead of abstractions where possible ▪ es5-shim, intl.js, etc. ▪ Use libraries that are shareable ▪ lodash, superagent, moment, etc. ▪ Use bundling for building your javascript ▪ e.g. webpack or browserify
one simple API change: ▪ Client: React.render(Component(), domElement, callback); ▪ Server: var html = React.renderToString(Component()); ▪ Clean programmatic page composition using components ▪ DOM synchronization is easy, now only worry about state management
from action creators Dispatcher Stores React Component React Components Stores are populated by actions from the dispatcher Component needs to render based on a certain state from a store
class, registration of the handler needs to be done for the instance ▪ Dispatches should be scoped to the request too, so that data isn’t sent to every request’s store instance
functions ▪ Instantiate a new Dispatchr per request ▪ Dispatchr creates instances of stores as they are needed and dispatches the actions https://github.com/yahoo/dispatchr
var dispatcher = new Dispatcher(); showMessages({}, function (err) { if (err) { next(err); return; } var html = React.renderToString(ChatApp()); res.write('<html><head><title>Chat</title></head>'); res.write('<body>'); res.write('<div id="app">' + html + '</div>'); res.write('</body>'); res.write('<script src="/build/js/client.js"></script>') res.write('</html>'); res.end(); }); }); server.js
components are going to be rendered No way to know which components are being rendered. Need some step between a full component hierarchy and being rendered to a string.
routes between server and client • Shared route matching logic • Create paths from components using routes names and parameters • Example: context.makePath(‘user’, { id: 1 }) // returns /user/1
server side web services • Expose them via an XHR endpoint • Access your services from an action with the same code both server and client • Example: context.service.read(‘messages’, {/*params*/}, callback) • Client uses XHR, server calls service directly