
Isomorphic JavaScript: The Future of Web Apps - aitskovi
http://nerds.airbnb.com/isomorphic-javascript-future-web-apps/
======
quarterto
You keep using that word. I do not think it means what you think it means.

Using precisely defined mathematical words in contexts where they only make
sense vaguely to a layperson ruins their original usage. Make up a new word.
Repurpose a shitty English word. But leave our damn maths words alone.

Old man quarterto shakes his fist at you! Get off my smooth, compact lawn!

~~~
frontendbeauty
(author here) Good point. TBH, I have no idea what "isomorphic" means in the
mathematical sense.

I was inspired to use "isomorphic" from a 2011 article by Nodejitsu [1]. It
seemed like a fine way to describe this approach. I would gladly use a better
would if I were to find one.

[1] [http://blog.nodejitsu.com/scaling-isomorphic-javascript-
code](http://blog.nodejitsu.com/scaling-isomorphic-javascript-code)

~~~
btilly
I like _relocatable JavaScript_.

~~~
yuchi
It's the first time that I hear about it, and I do not dislike _relocatable_
at all

------
natural219
At the Meteor meetup last week, David Greenspan outlined an interesting
approach to how Meteor UI separates the "template-parsing" logic from the
"rendering" logic with an intermediate representation (in Javascript) of the
steps you need to take to produce that HTML. Check out the video (relevant
slide is at 16:47, but the entire talk is awesome):

[http://www.meteor.com/blog/2013/11/06/david-greenspan-at-
dev...](http://www.meteor.com/blog/2013/11/06/david-greenspan-at-
devshop-9-meteors-new-rendering-model)

The cool thing is, other template languages (like Handlebars, Jade, etc.) can
compile to this intermediate representation, which then gets rendered on any
updates.

If the front-end community could agree on a protocol for how to represent
these steps in, say, JSON, then we could be on our way to a world where you
could use any rendering engine with any template library, on the client or the
server.

That is, if the community could agree on a representation :)

------
thurn
We do this sort of thing on the site I work on, Google+. Initial page-loads
are rendered on the server, subsequent page-loads are rendered on the client.
Really good for performance. It's just the templating system that's common
code, though, the server is still Java.

~~~
frontendbeauty
(author) Cool! What's the JavaScript runtime on the server? Something JVM-
based?

~~~
thurn
The server code is still Java, but our template language
([https://developers.google.com/closure/templates/](https://developers.google.com/closure/templates/))
compiles to both JS and Java.

~~~
sitkack
Why not render the templates in PhantomJs and have a user account that can
push the rendered template back into the server cache. No need to duplicate
the work of writing two backends. Or hell, just use Rhino and generate the
reified pages on the server.

Also, you can't patent this now.

~~~
lennel
The soy templates have a java (tofu) backend already (several years old).

The phantomjs idea is a shit idea and should go away. Phantom is fine and good
for headless testing (hells we use it for quite a bit else) but seriously it
is not a solution for a real load.

~~~
sitkack
In my scenario an alternative (Rhino or PhantomJs) engine would generate a
page _once_ and then push that rendered page to the server. No real load would
be sent to it. Single code path for all template rendering. Zero cross
implementation bugs and the client still gets a fully reified page on first
load.

Shit idea, lil harsh.

~~~
peterhunt
Shit idea is a little harsh for sure, but the problem is when your page relies
on dynamic data and you can't prerender it. It's just too expensive to boot up
a DOM on the server.

~~~
lennel
Why would you pre-render if your data is not changing continually? Don't you
just have static content then?

------
gmjoe
This smells like over-engineering to me...

In my experience, including rendering code both server-side and client-side is
overkill. Just put all the rendering and templating code client-side, period.

If you want your page to appear more quickly, then instead of loading content
data with AJAX afterwards, just include JSON arrays of content directly within
the HTML source itself, and use JavaScript to populate the page instantly,
even as it loads.

(Obviously SEO is a different case, but there are tools built for that
specifically.)

~~~
frontendbeauty
The approach you mention is much easier. However, it does make for slower
perceived page load times, even when serializing JSON on the page, because the
browser has to fetch, parse, and evaluate JS files before rendering the HTML
into the document. This can take many hundreds of milliseconds, especially on
mobile devices.

In _my_ experience, server-side rendering has led to a much better UX.

------
themanr
A great thing about the web is that a multitude of server side languages can
be used. While I don't ever want to have to write the same template twice,
having everything converge on nothing but Javascript doesn't seem like a very
inspiring future to me.

~~~
danpeddle
If you are building a service or API, then you can do that in whatever
language you like. The natural language for writing client side apps is JS
(ok, the only language, for now).

~~~
frontendbeauty
Correct. If you're already writing a bunch of JavaScript for the client-side,
then just think about this approach as migrating some of that client, UI logic
to the server.

~~~
CmonDev
To have two problems instead of one?

~~~
frontendbeauty
There are already two problems, if you're building a rich client-side web app.
Have you done this? If so, you would understand the problem.

------
acjohnson55
I like the basic idea, but my hope is that we can go the other direction and
bring more interesting languages to the client side. I know this is done to
some extent using JS or Asm.js as a compile target with a whole bunch of
existing projects. But it would be great to see this really move forward.

It seems like CoffeeScript did this rather successfully, and with source maps,
the debugging story is getting better too. Any reasons why this might not be a
more compelling future than the "JS everywhere" vision?

~~~
markc
Consider Clojure - an interesting language indeed, and the browser variant
(ClojureScript) is gaining lots of interest.

~~~
CmonDev
Make it native across major browsers - that would be cool. At the moment it's
just another transpiler.

~~~
acjohnson55
I'm not sure anything's fundamentally wrong with transpilation.

------
Randgalt
Wasn't this the idea with GWT so many years ago? In GWT's case, it was Java on
both sides. I don't believe that it solves the problem and I don't believe
Javascript on both sides will solve the problem.

This is a classic "impedance mismatch" like O/R mapping. At the end of the
day, there may be no good, i.e. simple, solution. It is inherently difficult
and messy.

~~~
esamek
GWT is not Java on both sides. Its Java on the server, Javascript on the
client. The Java client side code compiles to Javascript...the abstraction is
way greater than what OP is presenting. (JS & JS)

GWT is/was a terrible amount of overhead baggage, but had some brilliant event
systems and DOM tricks for its day.

~~~
dragonwriter
> GWT is not Java on both sides. Its Java on the server, Javascript on the
> client. The Java client side code compiles to Javascript..

And the Java server code compiles to JVM bytecode. Languages often compile to
some other form to run, and the fact that the compilation target is different
for different parts doesn't change that the programming language is the same.

------
Breefield
I'm curious to see how this shared rendering between client/server plays out
for non JS based frameworks such as Django, Rails, etc.

I've been feeling the burn myself—the desire to fully switch to handlebars
templates in my Rails app. The expensive part would be building my API out
more than I have, because I rely on associations in Rails view renders.
However, gaining 1 template engine to rule front & back.

~~~
frontendbeauty
(OP here) Probably your best bet is to create a small Node web service that
takes a template name and data and returns HTML. Then your (Rails, Python,
PHP) app can call out to that in the request cycle.

Instagram.com does something similar; it's a Django app.

~~~
icebraining
Seems to me that the approach with best separation of concerns would be to
redirect the initials requests directly to node, which would then call the
Python/Ruby/etc API to get the data to render the template. After that, the
browser JS could call the API directly, and so the latter would never have to
know about templates at all.

------
mindcrime
_Now, the Web has matured into a fully-featured application platform, and fast
JavaScript runtimes and HTML5 standards have enabled developers to create the
rich apps that before were only possible on native platforms._

Eh, saying "matured into" implies that the current state is somehow better or
more desirable than the previous state, and somewhat implies that this was the
expected / desired goal state. I reject all of those implications. I posit
that it would be more correct to say that "the Web has been mangled, bent,
distorted, twisted and hacked into a fully-featured application platform..."

A Web _browser_ should be good at _browsing_ , trying to make it into an
application runtime is a "separation of concerns" violation of the first
magnitude. It might work, but let's not pretend there aren't other choices, or
forget to continue researching alternative approaches to delivering
applications over the Internet.

------
akbar501
AirBnB's Rendr library is not a JavaScript, and only JavaScript solution. It
is however a library that allows you to mostly unite your web rendering layers
on the web client and application server.

Look at the first diagram in the article and you'll notice that the author
shows 3 environments:

1\. Client (obviously the browser is JS) 2\. Application Server (the server-
side rendering environment = what he says can now change to JS thanks to
Rendr) 3\. API Server (use whatever you want here - JS, Java, Ruby, Python...)

And, in production you will no doubt need a "static" server as well (for
rendering privacy, tos, etc. pages). Plus all of the other production systems
(like a queue, stream processing, and so on) that are not JavaScript
environments.

If you check out his example code you'll see that he actually sets up example
04
([https://github.com/airbnb/rendr/blob/master/examples/04_entr...](https://github.com/airbnb/rendr/blob/master/examples/04_entrypath/index.js))
with a subapp for a static page.

Also, if you look at the react-moment branch in the isomorphic tutorial repo
([https://github.com/spikebrehm/isomorphic-
tutorial/blob/react...](https://github.com/spikebrehm/isomorphic-
tutorial/blob/react-moment/index.js)) you'll see that he's proxying a dummy
API server to a route on the application server.

------
hippich
Funny thing, had related talk today with my co-worker...

Anyway, so problem currently is that client devices are slow and HTTP requests
are expensive/slow. If these were not issues - I guess rendering on a client
would be just fine?

If above is correct, I do not see good reason for smallish
websites/apps/whateverucallit fallback on server rendering, as it looks like
every single year mobile devices getting faster and faster. And we have SPDY
on a way to mainstream.

Do I want to wait 3 seconds to get HTML or wait 100ms to get bootstrap code
and see pieces rendering as data comes in? Probably doesn't matter, since it
will take roughly same 3 seconds to render it on client side.

Ultimately, perceived responsiveness of webapp depends a lot on particular
implementation. If you wait for all data required for page to render - yes, it
will be slow. If you render pieces of page as data comes in - user sees that
something going on and this is good enough. Why it should matter where data
will be converted to presentation, on server or on a client? It is still
waiting. And if client is not happy with it? Buy beefier hardware!

~~~
babby
> 3 second to get HTML

No server should take more than 100ms-500ms on a sufficiently cached page to
process and to begin transferring, in non-edge cases. The only thing that
could take that long is a shitty datacenter/vps, and as such, transfer
speed/latency limits will encumber all types of requests.

In the end, you still have to transfer data from databases, so ignoring that,
client-side template rendering seems like a non-issue to me. Surely it's never
the latency issue unless you're serving at ~100+ requests per second, which
translates to many millions of requests a day, and I don't believe 99% of
websites are doing this.

------
williamcotton
There is a confusion between isomorphism and monomorphism when it is related
to JavaScript as it runs in the web browser runtime compared to the node
runtime.

I feel this tension is at the root of the CommonJS vs AMD discussions that
have been taking place recently as well as issues related to npm, bower, and
browserify.

Monomorphic code, while being very easily shared amongst different runtimes,
still needs to aware of the mechanisms, strengths, and weaknesses of those
runtimes!

Projects like browserify-cdn and sites built with on top of it like
requirebin.org do a lot to bridge the gap but raise some interesting questions
about wrappers like UMD.

I feel there is room for a better protocol for sharing code between the
different environments.

I'm currently doing some research on the subject and plan on writing a spec
and implementing some example interfaces.

BTW, projects like Bower head in the opposite direction and seem painfully
unaware of their actual context...

I mean, installing a package manager to then install a package manager should
raise some eyebrows, right?

------
tfb
I've considered doing exactly this (using Node.js) based on the same paradigm
as the Unreal Engine. Epic devised a very effective way to code for both a
client and server at once within the same class(es), where server->client,
client->server, and other types of replication are as easy and intuitive as
anything else. I think it would be perfect for real-time web applications
where multiple users interact with each other at the same time. I'd advise
anyone interested in these ideas to check out how the Unreal Engine does it.

Edit - A couple of unofficial but useful links:

[http://wiki.beyondunreal.com/Introduction_to_replication](http://wiki.beyondunreal.com/Introduction_to_replication)

[http://wiki.beyondunreal.com/Legacy:Replication_De-
Obfuscati...](http://wiki.beyondunreal.com/Legacy:Replication_De-Obfuscation)

------
camus2
why the use of the word Isomorphic in that context ?

~~~
romanovcode
To sound smart.

------
leeoniya
i hope the future of web apps isn't also pages like this one that screw up my
preferred scroll-wheel speed (FF) :(

------
lucasjans
Conspicuously absent from the author's article was Angular. What is it about
Angular that doesn't lend itself to this dual purpose frontend and backend
infrastructure?

~~~
spion
Lots of potential hidden state as well as the need to support the entire DOM
API server-side. For example, directives may add hidden state to the DOM and
assume full availability of DOM API (even jQuery). The server will have to
support all that

Also, you'll have to re-do the entire rendering on the client, then swap the
server-generated DOM with the client-generated DOM. Its probably possible -
but is it worth the effort?

~~~
ilaksh
I did it. Not really super hard. [https://github.com/ithkuil/angular-on-
server/wiki/Running-An...](https://github.com/ithkuil/angular-on-
server/wiki/Running-AngularJS-on-the-server-with-Node.js-and-jsdom). But
[http://prerender.io](http://prerender.io) is a lot easier and works for
everything.

------
raphinou
I've started developing some simple apps with Wt
([http://www.webtoolkit.eu](http://www.webtoolkit.eu)) and it's really cool.
It lets you develop web apps in a widget oriented way, and completly abstract
the client/server communication.

It's not javascript on the server but that's fine. I actually used the Jwt
(java version) with Jruby and Groovy, which is translated from their C++
codebase.

------
JDDunn9
So then you couldn't use a CDN to load your JS files, which might kill your
performance gains. How does this change loading partials?

I disagree about the complexity. I've build Angular apps with a RESTful
backend that couldn't be simpler. I also haven't noticed any performance
issues. It's faster than traditional sites for me. SEO is a problem though.

~~~
frontendbeauty
Why couldn't you use a CDN for the JS files? We most certainly do.

------
avolcano
My main concern - how does application state get handed off to the client-side
code after the initial render? Sure, it's nice to have some pre-rendered
templates, but at some point it needs to "transition" cleanly to the client.

~~~
akbar501
I just started hacking on Rendr last night, so I don't know if it shares state
between Express on the server and the client-side app. My guess would be that
Rendr does not have this built in as it's stated design goal is to stay
small/modular.

However, Yahoo already released a solution for shared Express/client state:
[https://github.com/yahoo/express-state](https://github.com/yahoo/express-
state)

~~~
fieldforceapp
How does one go about debugging such a framework, state synchronization errors
seem like they'd be a nightmare?

------
poissonpie
Interesting read. I really think that the SEO problems faced by SPAs will
eventually become a non problem......web crawlers will adapt to the technology
that is rendering web pages because indexing is their "product".

------
michaelwww
I'm having a brain freeze here. How do you render a DOM on the server and then
push it out to the client? Convert in memory DOM to a text/html representation
before sending?

~~~
frontendbeauty
There are a few options. Easiest is to just render HTML strings on the server,
not actual DOM. But, you can also use a DOM implementation if you want to,
like jsdom or PhantomJS, and then capture the outerHTML of an element as an
HTML string to serve. But, that is slower. React.js has a nice middleground
approach; it has a fast pure-JavaScript DOM abstraction that can emit either
DOM (browser) or HTML (server).

~~~
michaelwww
> Easiest is to just render HTML strings on the server

That's old school way. Sometimes old ways are presented as new, which confuses
me.

> then capture the outerHTML of an element as an HTML string to serve

That makes sense. Do the fancy building on the server and then convert it for
transport

> React.js

That sounds interesting. You answered my question enough that I can do more
research. Thanks.

------
BUGHUNTER
I can not sort by prize on the airbnb listings? Also I do not want to see the
map, but can not find a way to disable the map.

------
etanazir
I think its obvious Twitter moved to server side rendering for control /
profitability reasons. Not performance.

------
Kiro
If a single-page app is dependent on SEO it shouldn't even be a SPA to begin
with.

------
csbartus
Is this something like Rails's PjAX or Turbolinks or completelly different?

------
ilaksh
[http://prerender.io](http://prerender.io)

------
VaedaStrike
I'm going to stick with learning me some pedestal.

------
knappador
"She's an iso"
[http://www.youtube.com/watch?v=y8nXRQQ0bjA](http://www.youtube.com/watch?v=y8nXRQQ0bjA)

Mostly Django user attempting to ask from outside the Node/server-side js
community for an explanation of why we're invoking "isomorphic" here: As far
as what's going on, are we just saying that the js for rendering the page is
equally capable of talking to the API and doing the DOM work while running on
the server as it is when downloaded, interpreted, JIT'd etc before fetching
the actual request content? Does this mostly eliminate an extra RTT to the API
if the js/web application server experience relatively zero RTT due to
network/physical proximity to the API server? Does this incidentally make SEO
possible while having fat clients and server-side initialization all in one
setting and with mostly one code base?

Assuming I'm on track, working backwards towards understanding the
implementation as it relates to "isomorphic", if a program's output state is a
valid input state to initialize the program (we're talking fat, stateful MVC
clients after all) state, then all that's needed to re-create the entire
execution state of the current program is to copy itself into the output in
such a way that it will be run upon receipt (we link js files in the page).
I'm going to take a wild guess that the output state of the client doesn't
have the necessary template tags etc used when a cold page is rendered, server
or client-side, so the server has to serialize some of the state and pump it
into the copy of the program to make it as if the client we're sending is the
client that rendered the page, keeping the client's internal representation
consistent with the state of the page.

If this is true, we're taking a program that cannot be initialized from it's
own output and modifying it to be a program that achieves the same effect. JS
is modifying JS, and is therefore said to be "isomorphic?" It still sounds
like a glorified way to describe a serialized execution state, one that
happens to involve a program in a language outputting a valid program in the
same language, but the purpose is to achieve the effect, as far as the
developer is concerned, that the output is a valid input, albeit with an
intermediate technique to make the abstraction hold water.

If I'm on track, then I have to say it's rather as if we have a fat client,
output of one render, serialized client state (because the DOM is not
sufficient to re-create the program state or else our client js has to
initialize from one format that's programmer friendly and one that's program-
friendly), and necessarily a third-leg responsible for injecting the client js
and serialized state as js into the output.

Standing to see the mauve dusk of my life against the impending rain of spears
and arrows, I must ask if we can not simply call the js necessary to achieve
the equivalent state of running everything client side a "continuation" and
call the entire technique "client continuation programming?" with it
implicitly understood that creating the continuation involves a third piece of
program? I'm prepared to die. I just want to know.

------
tonetheman
one man's isomorphic javascript is another man's text file...

------
shire
this is interesting so Javascript can now be used for server-side which
removes the need for Ruby on Rails and Django basically? can someone summaries
this article, time is of the essence.

~~~
doorhammer
If you're not familiar with server side javascript, looking up node.js is a
good place to start.

