Update March 2018: Two years on from the original publish date, Aurelia finally has support for server-side rendering.
This means it is now possible to create isomorphic web applications in Aurelia that work with and without Javascript disabled, resulting in faster initial rendering speed. If you would like to see a working example, the Skeleton repo has you covered.
Now, onto the existing article.
Isomorphism is all the rage in the Javascript world. The server can return rendered HTML complete with pre-computation (converting bindings and templating specific events already taken care of increasing initial load speeds and time to paint quite substantially.
A classic example of simplistic isomorphism can be found in the form of ReactJS which treats this approach as a first class citizen and has done so from the beginning. Meteor which is not a framework or library, but rather a full-stack platform also has support for isomorphic workflow baked in as well.
Unfortunately at the time of writing this article, isomorphic Javascript is not currently supported in Aurelia. Although such functionality is eventually planned, in the meantime we have to come up with workarounds to compensate for the lack of support.
The question we need to ask ourselves here is, do we even need isomorphism support in Aurelia and just how many people actually need it versus how many people just want it because React and even Angular 2 can support isomorphic applications?
Do your product and business requirements dictate the need for isomorphism? We should not let the latest opinion article on Hacker News dictate our choices. Do you even know what an isomorphic application looks like, how it should be built and how it will affect other pieces of the infrastructure puzzle?
What is Isomorphic Javascript?
I’ve seen many terms thrown around describing what is akin to a shared codebase between front and back, including Universal Javascript, but the isomorphic term seems to be the most popular way to describe it.
Speaking of isomorphism in Javascript specifically it means Javascript code that runs on both the server and client. Popular amongst front-end developers is building isomorphic applications with React and something like Express on the server-side.
If you have ever worked with Meteor before, you would know Meteor specifically comes with support for isomorphism out-of-the-box without needing to configure anything.
In Meteor you have utility methods for checking the context in the form of isClient
and isServer
as your Javascript can work on either all.
What about Aurelia Enhance?
Even though Aurelia does not offer isomorphism support in the true sense of the word, it does have an enhance API which essentially allows you to return markup from the server on page load and then have Aurelia load it, or “enhance it” to allow for faster page loads.
Think of Aurelia’s enhance capability as partial isomorphism, sorta. It won’t allow you to throw back a server-rendered template and have Aurelia intelligently pick it up, but being able to render an Aurelia custom element or use an attribute in the returned server markup does have its benefits.
The reason that enhance does not offer true isomorphic support is because you can’t render an Aurelia application on the server and send back the rendered HTML.
You can only send back HTML with Aurelia resources in it, but the client still has to do the heavy lifting on initial page load so really enhance solves nothing. It is more for being able to use Aurelia components inside of an existing application or do things with the server providing data in the HTML.
Is isomorphism a fad?
There is merit in using isomorphism in your Javascript single page applications. Not everyone is using your application on a Mac or PC running the latest version of Chrome. There are resource restrictions, battery and CPU constraints as well.
As intelligent and well-written as modern SPA frameworks are, they still lean on the browser to do the heavy lifting during the initial bootstrapping phase. This initial render phase is often the most expensive part of your app, but it is not necessarily the sole bottleneck.
I think there is definitely a time and place when deciding to use it, but I feel as though most people are adopting this approach to their web applications without truly knowing what isomorphic Javascript is, how it can help or what it is for.
The concept of isomorphism is not really that new, for years people have been rendering their templates and using client-side libraries to manipulate them. Libraries like React and the platforms like Meteor and Loopback have made it more popular in the last couple of years.
There is a little bit of learning curve going full isomorphic as well. It requires a rethink of your application structure and backend setup. There are security concerns you need to be aware of when deciding to make your Javascript universal and publicly visible.
Debugging server-side Javascript can also be a nightmare for an inexperienced or primarily front-end developer. There are Node.js specific debugging tools, but it means you have two separate tools and processes for testing the client and server side Javascript you are writing.
Unless you are working with Meteor, there might be instances where you struggle to separate back from front-end Javascript, when you accidentally write something that only works for the client or vice-versa.
Isomorphism is a trap
Honestly, we lived without being able to build isomorphic applications before Node.js and supported SPA’s existed, I do not understand why all of a sudden it became an essential requirement to be able to write isomorphic applications.
I realise that development has not only grown in complexity but size. Most Javascript frameworks hover around the 500kb mark and that is without including polyfills.
I see the argument for using isomorphic Javascript being touted as this magical bean that will make your application performance off the charts. It’s a trap.
Yes, isomorphism will make your application load faster, but it won’t make your web server fast if it is being crushed by visitors, if you don’t have a CDN and someone in Poland is loading your Australian hosted website contending with insane latency issues, if your database is running unoptimised queries or your first page load is 10mb.
A lot of issues I see in regards to performance are factors beyond the control of the client. Implementing a paradigm and failing to devote the same amount of attention and love towards the other parts would just give you a Ferrari with bad compression in the engine.
You might have a fast and visually pleasing car, the engineering is there, but the engine is just not able to give you the power you need until you get it fixed.
Do we need isomorphic support in Aurelia? Well, we don’t need it, but it would be nice and it is eventually coming. It is rare that I personally would ever need to support it.
The one benefit that isomorphism has is SEO purposes. Although Google has been pushing ahead with its support of client-side SPA frameworks to the point where performance becomes the primary reason for isomorphic use.
I also don’t use SPA frameworks for public facing sites. Even going back to the early days of Angular, it was only used for applications that required a user to log in and other purposes that do not benefit from SEO nor should be indexable.
Do you want it in Aurelia and if so, what use-cases based on past and present projects required the use of it that could not be done with what we already have? I think we need isomorphic support in Aurelia, but I also think there are more pressing issues that take precedence over isomorphism support in Aurelia.
Hi Dwayne,
That’s a really great post!
I quite don’t get the SEO argument. Once google robot crawls my site it receives precompiled version of it, but when indexing other pages within the domain – does it also receive precompiled versions or does it have an Aurelia (or generally speaking a JS app) running that will act as a SPA and just fetch data for bindings?
What I’m thinking is whether it would be possible to actually place a headless browser behind nginx or something and route crawlers to it, so the crawlers would receive already compiled pages without a need to go isomorphic.
Do you have any thoughts about that?
Thanks!
Thank you for the post.
Social sharing is also a problem. We cannot assume that Twitter, Facebook, Linkedin and others will have the same capabilities to render link previews. Sure, Google and Facebook maybe can handle javascript render, but the best solution is to have a way to have a static render of the content first.
And that’s my biggest head scratcher with SPAs ATM. Things get tricky when you need to facilitate link previews when sharing certain data driven content.
Hey is use enhance version of Aurelia thats great.
my is persian but will give you a good insight to how use Aurelia enhance technique.
I use it and completely was satisfied with that.only issue is load time. it takes too much time too load my Aurelia components on Android devices but mm apple devices performance for loading is great I ddnt get any clue about the reasons you can check my site here:
http://otex.ir