isomorphic i·so·mor·phic (ī’sə-môr’fĭk)

Having a similar structure or appearance but being of different ancestry.

Ever since the invention of NodeJS people have loved the idea that you could “share” your JavaScript experience across the stack. This (in theory) has many benefits including less context switching between languages, easier transition between front-end and back-end, and perhaps the most hopeful benefit was the ability to even share code. Today i’m going to show you how far we have come and what is possible with isomorphic JavaScript.

Alright, we all know It is possible to use utilities like Lodash universally with the help of browserify or webpack. What about environment specific things such as AJAX? Check — Isomorphic fetch allows us to do just that. What about moving forms and files around? Check — Isomorphic formdata works perfectly with isomorphic fetch as well! What about if I need to be able to detect my environment; I’m not using meteor?! It’s covered. Even the DOM can now be made isomorphic with the help of the “Virtual DOM” implemented in libraries such as React, Deku and many others. You can even opt out of the virtual DOM altogether and get right back to writing the simple “static” html with tools such as morphdom, set-dom and diffHTML.

This example, although simple, will batch send 100 emails at a time to a custom api and can work just fine in NodeJS or the browser.

This is starting to look pretty cool. I can now write an app that uses the same utilities, ajax and templates in both Node an the browser! Well, we’re not quite there. There’s still too much missing! We need routing (with redirects), sessions, cookies, state management and more to make a universal app! Node lets us delegate most of these tasks to frameworks such as Express and Koa and allows easy organization of features into middleware. You can isolate features and I can test them easily! It’s a simple, top down, pluggable approach to building html — You can easily follow a request through the entirety of your app (Sound like flux anyone?). Why can’t we build DOM in the same organized way? React brings us close, but it’s still not enough. React router brings us closer, but it’s unfamiliar and bulky.

Well, my friends, i’ve been working to make isomorphic JavaScript more enjoyable and easy to write. With less boiler plate, less context switches from client to server, free progressive enhancement, faster load times, SEO and best of all a simpler way to think about web apps. There is now a way to share 90% of your browser code with node. It’s a framework that has been in development for over a year thanks in part to my gracious employers at Tiller Digital and the countless others who are working on bridging the gap for isomorphic tooling. It’s name is Rill.

Great. Another framework. What does it do?

Rill is an abstraction over the part of Node we all use most, the HTTP server. However it exposes the http api in an isomorphic way thanks to @rill/http. Routing, redirects, cookies, sessions, refreshes, error handling and even common headers for things like the “user-agent”, “referrer” and “locale”. You can finally access all of the data about a user or request from the same api, client or server, and it just so happens to be the same as Node.

Rill is a bit more than just this though, @rill/http is only one module. Rill (the main library) is more akin to Express or Koa and shares a fairly similar api. It enables middleware in an isomorphic environment and provides the final piece for any app. A way for data to flow. You can check out the documentation here.

Thats it, the index page is now fully capable of being rendered by the browser, or the node server. But thats not very impressive, what about navigation? What about “/away”?

Now you can navigate back and forth and the browser will just handle it. Feel free to turn off JavaScript as your server is also perfectly capable! No awkward tiptoeing around your environment, no “server code” or “client code”, just render your views!

This may be pretty cool, but if my page was just static content then this is overkill (although it has some benefits). What about my CRUD app? How can users enter in data? Well, the answer is simply another question “How would you do this without front-end JavaScript?”. Rill lets you pretend that your browser is a fully capable node server, it can even handle form submits! Lets add a form!

Now this is awesome, and it runs perfectly in Node and the Browser. We can program like we are in Node, and progressive enhancement comes easy when the browser can take over. Need a search input that searches while you type? Simply use React to trigger the submit button “onClick”. It will just work, and be just as fast as doing it manually. With the added benefit that, if the JavaScript fails, your server knows exactly how to “react”!

This is just the tip of the iceberg. Modules for this style of development are still being worked on and the limit is yet to be reached. Personally I think tools like “Node Canvas”, and the “Node File API” could open up progressively enhanced image manipulation. For the current list of Rill compatible middleware just click here, or here.

And thats it. You get the expressiveness and simplicity you were once accustom to with your old “server only” solutions with the ability to off-load the bulk your logic to the front-end when available. It’s a lot to take in, and it’s certainly a different way of building front-end applications but it’s also familiar. Write your lovely Node code and have it work in both places. Fast initial render in the server, faster re-renders in the browser. The best of both worlds, the apex of JavaScript web development, the holy grail.

If you have questions about Rill, Isomorphic/Universal JavaScript, or how to build real applications this way please drop by the gitter page.