Skip to content

Instantly share code, notes, and snippets.

@3rd-Eden
Created March 16, 2015 13:04
Show Gist options
  • Save 3rd-Eden/1699ba8b7bc70042439c to your computer and use it in GitHub Desktop.
Save 3rd-Eden/1699ba8b7bc70042439c to your computer and use it in GitHub Desktop.
BigPipe & React sitting a tree.
  • BigPipe and React
  • React components
  • Share state
  • Server Side rendering
  • Modularization of components
  • Re-initialization
    • checksum
    • event adding
    • html bloat
  • JSX
  • Fittings
  • separation of concerns.

Over the last couple of weeks I had the pleasure of taking the much hyped React framework for a spin by working on an proof of concept. Some people claimed it’s the utopia of front-end development because of it’s magical virtual dom capabilities and it’s seen as the successor or iteration of Facebook’s BigPipe pattern or is said to be the framework what the BigPipe should have been. So the question is, does it live up to it’s buzzword reputation?

As author of the bigpipe framework which implements the BigPipe pattern for IO/Node.js I was curious how this would play out. It was already quickly obvious that React doesn’t really focus on the server side part of building web applications. So it would be great to see if the patterns could complement each other, where BigPipe focuses on the server and React on the client.

For me, the proof of concept that we build had to tick a couple of boxes. It wasn't just about how we can get React and BigPipe to work together but also React's patterns apply to a building some really complex applications. So the following questions had to be answered.

  • Maintainability The code that we are producing is it easy to maintain even for new developers?
  • Modularization Is the code modulair and re-usable between projects.
  • Internationalization i18n support is a must, blindly assuming that people only speak your language is idiotic.
  • Productivity Does our productivity suffer or increase.
  • Learning curve How good is the documentation and is it easy enough to get started with.
  • Isomorphic Can the code that we write be shared between server and client?
  • Performance What kind of positive or negative performance impact does it have.

React server side rendering

In BigPipe it’s already possible to share the templates/views between server and client. This is a feature we did not want to abandon when using React as it reduces context switching and improves maintainability of the project. Now React does come with with 2 helper function in order to render it’s components on the server.

var html = React.renderToString(Component);

The renderToString and renderToStaticMarkup methods transform the React Elements that you return in your component’s render method to a regular HTML string. You can then write this output on the server and be done with it.

On of the problems that I had with React was that JSX templates are always embed inside your render function. This means that in order get a HTML output you need:

  1. Create a new React component
  2. Write the template in it’s render function
  3. Transform the written React component using the react-tools module so it transforms the JSX HTML in to React.createElement calls.
  4. Render all the things.

The biggest problem I have with this approach is that there is no longer a separation of concerns between your template and the rest of your logic. In addition to that, the react-tools need to process your whole JS file just to be able transform the JSX syntax as it uses AST (Abstract Syntax Tree) transformations which leads to additional compilation time overhead. This was the first thing we wanted to tackle. We wanted to keep using JSX as writing all the React.createElement barf becomes unmanageable quite quickly. So the solution was to extract the JSX out of the render method and to it’s own dedicated template files. In order to make this process a bit easier we created a new module called react-jsx.

react-jsx

Extracting the JSX template out of the render method has proven to be a bit challenging then initially envisioned as template requires access to a scope where it gets all it’s data from. For example:

<div>
  <input type=“text” value={defaultValue} />
  <button onclick=“alert(‘clicked!);>Click Me!</button>
  <ul>
    {[‘un’, ‘deux’, ‘trois’].map(function(number) {
      return <li>{number}</li>;
    })}
  </ul>
</div>;

Is transformed into:

React.createElement(“div”, null,
  React.createElement(“input”, {type: “text”, value: defaultValue}),
  React.createElement(“button”, {onclick: “alert(‘clicked!);}, “Click Me!),
  React.createElement(“ul”, null,
    [‘un’, ‘deux’, ‘trois’].map(function(number) {
      return React.createElement(“li”, null, number);
    })
  )
);

As you can see in the snippet above the defaultValue is now expected to be in the global scope. As normally it’s wrapped in a render function the defaultValue would have become local to that scope. But as we’ve extracted the template out of the render function we lose that ability. So the solution is to wrap the outputted React.createElement in a function, but the only problem remains is that we need introduce this defaultValue variable some how. We can do that using our beloved and praised with statement so we can introduce the properties of an Object as local variables. And what I just described is exactly how the react-jsx module works. So we can just render templates using:

var Component = React.createClass({
  render: function render() {
    return mytemplate.call(this, { foo: ‘bar’ });
  }
});

But you don’t actually need to use React components anymore in order to render a template, you can call the mytemplate directly. It still returns React Elements but if we supply { html: true } as second argument it actually transforms them to a HTML output. After integrating this directly in to temper it allowed us to use the same template language everywhere. NEATO:

var Pagelet = require(‘pagelet’);

Pagelet.extend({
  view: ‘template.jsx’
}).on(module);

Re-initializing the components

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment