SlideShare a Scribd company logo
unlucio
Senior Software Engineer - Namshi
Dive Master - PADI
Remote Nerd - WEBdeBS
Back to the future:
Isomorphic javascript
applications
An isomorphic javascript application:
What is an “isomorphic application”
Why did we need one
How did we build it @ Namshi:
Requirements
Choices
What did we actually do
Isomorphism
Isomorphism is a very general concept that appears in several areas
of mathematics. The word derives from the Greek iso, meaning
"equal," and morphosis, meaning "to form" or "to shape.”
wolfram.com
http://mathworld.wolfram.com/Isomorphism.html
Isomorphic application
It’s a dynamic website capable of generating its html on
both server and client side, virtually using the same
exact code in both environments
and a website
is a bunch of nicely presented html
with an interactive layer on top
to be isomorphic
we need to stop at the html
take a note for future self!
Why do we need one?
Why do we need one?
Robots: search engines don’t cope with SPAs
Why do we need one?
Robots: search engines don’t cope with SPAs
Loading speed
Why do we need one?
Robots: search engines don’t cope with SPAs
Loading speed
Javascript doesn’t “fail safe”
@ Namshi…
We had to turn
this…
Back to the future:  Isomorphic javascript applications
in to
this
See the difference?
Back to the future:  Isomorphic javascript applications
SPA Page Isomorphic Page
SPA Page Isomorphic Page
~190Kb js Target 100Kb js
SPA Page Isomorphic Page
~190Kb js Target 100Kb js
~ 40p page speed at least 90p page speed
SPA Page Isomorphic Page
~190Kb js Target 100Kb js
~ 40p page speed at least 90p page speed
Angular.js ?????????
?????????
?????????
yup, we had to make a choice
Back to the future:  Isomorphic javascript applications
Back to the future:  Isomorphic javascript applications
We’re already using it on our SPAs
We’re already using it on our SPAs
Well known dependency injection
We’re already using it on our SPAs
Well known dependency injection
Data bindings
We’re already using it on our SPAs
Well known dependency injection
Data bindings
Jade (and we like it)
It’s ok but…
Making it isomorphic needs
quite a bit of tooling around
Back to the future:  Isomorphic javascript applications
Back to the future:  Isomorphic javascript applications
New and fashionable…
New and fashionable…
…we’re eager to try it :)
New and fashionable…
…we’re eager to try it :)
The virtual DOM looks amazing
New and fashionable…
…we’re eager to try it :)
The virtual DOM looks amazing
Flux (once you get it) seems quite a good idea
New and fashionable…
…we’re eager to try it :)
The virtual DOM looks amazing
Flux (once you get it) seems quite a good idea
JSX…
New and fashionable…
…we’re eager to try it :)
The virtual DOM looks amazing
Flux (once you get it) seems quite a good idea
JSX…
… but components are a nice idea too!
New and fashionable…
…we’re eager to try it :)
The virtual DOM looks amazing
Flux (once you get it) seems quite a good idea
JSX…
… but components are a nice idea too!
and The Internet says it can be isomorphic too!
Back to the future:  Isomorphic javascript applications
Let’s try it! :D
Examples and suggested techniques seems been
quite complex, with lots of structure and quite
opinionated
expectations slightly not met :’(
Yup, we’re back to square one…
Yup, we’re back to square one…
Back to the future:  Isomorphic javascript applications
ok… let’s try getting what we like…
ok… let’s try getting what we like…
data bindings
jade
flux
components
flux
capacitor
So, how does it work?
So, how does it work?
Step 1
Understand the view
Data Content
Template
Interaction
So, how does it work?
Step 2
Strip the interaction layer
Data Content
Template
Interaction
Remember our note: stop at the html.
So, how does it work?
What do we get form the api:
Data Content
{
data: [],
meta: {},
search: {}
}
{
data: “”,
meta: {},
search: {}
}
So, how does it work?
What do we get form the api:
{
data: “”,
meta: {},
search: {}
}
This guy is html!
So, how does it work?
Choose a template engine
Template
Jade:
our current angular ones
Nunjucks:
renders on client and server
let’s bring back
what we liked about React
Flux
Flux
Our data source: API
Flux
Our data source: API
State: the URL
Flux
Our data source: API
State: the URL
Add a little dispatcher to notify for data update
Show me the code!
Show me the code!
Server entry point
var app = require('express')();
var tpl = require(‘../shared/tpl');
var url = require('url');
app.get('*', function(req, res) {
var path = url.parse(req.url).pathname;
api.getData(path).then(function(data) {
var html = tpl.render('main.html', data);
res.end(html);
});
});
Show me the code!
And it’s client counterpart
var page = require('page');
page('*', function (ctx) {
var path = url.parse(ctx.path).pathname;
dispatcher.broadcast('URL_CHANGE', {url: path});
api.getData(path).then(function (data) {
dispatcher.broadcast('DATA_UPDATE', data);
});
});
page.start();
Components
Components
Activate on state update
Components
Activate on state update
Receive data
Components
Activate on state update
Receive data
Transform them if needed
Components
Activate on state update
Receive data
Transform them if needed
Delegate to templates for final html generation
Show me the code!
Show me the code!
Title Component
var tpl = require('../tpl');
var vpo = require('vpo');
module.exports = function(data) {
return tpl.render('title.html', {
text: vpo.get(data, 'meta.seo.pageTitle')
|| vpo.get(data, 'title')
|| 'Namshi.com'
});
};
Show me the code!
Title Template
<title data-iso-component="title">{{ text }}</title>
Hey but what about
my interaction?
Hey but what about my interaction?
well, according to legend: turns out that back in the 90s
humans were able to use websites simply clicking on links and
without fancy UI wow-effects
Hey but what about my interaction?
Interaction We call them: widgets
they react to UI changes
they attach to iso-components
interact with data-nm-*
and use VUE.js
Show me the code!
Show me the code!
var dispatcher = require(‘../../shared/dispatcher');
var menu = require('./menu');
var cart = require('../services/cart');
module.exports = function($dom) {
$dom.on('click', '#site_menu .search_trigger', function(e) {
dispatcher.broadcast(‘TOGGLE_SEARCH’);
e.preventDefault();
});
this.bind($dom, {data: { menu: menu, cart: cart }});
};
Show me the code!
<div id="site_header" data-iso-component="header"
data-nm-class="navigation_open: menu.shiftContent">
<ul id="site_menu">
<li><a href="" class="search_trigger">
<i>{{ 'search' | translate }}</i></a>
</li>
<li><a href="/cart/" class="cart_overview">
<span data-nm-text="cart.itemsCount">0</span></a>
</li>
</ul>
</div>
did we meet our target?
did we meet our target?
Isomorphism: yes :)
did we meet our target?
Isomorphism: yes :)
Size: 162kb (including templates)
did we meet our target?
Isomorphism: yes :)
Size: 162kb (including templates)
Page speed…
Page speed…
node.js
Browserify
Gulp
Nunjucks
Vanilla JS
express.js
VUE.js
Docker
Thank you for listening
Thank you for listening

More Related Content

Back to the future: Isomorphic javascript applications