SlideShare a Scribd company logo
1 of 71
Download to read offline
Building Isomorphic Apps 
@spikebrehm
Spike Brehm 
____________________________ 
@spikebrehm 
@AirbnbNerds
1. Why Isomorphic JavaScript 
2. Isomorphic in the Wild 
3. How to Isomorph
Why Isomorphic JavaScript
What is Isomorphic 
JavaScript?
JavaScript code that can be shared between environments.
i·so·mor·phic 
same form
http://blog.nodejitsu.com/scaling-isomorphic-javascript-code/
Persistence 
Client 
DOM manipulation UX JavaScript 
View layer 
Application 
logic Routing 
Backend 
Ruby 
Python 
Java 
PHP 
Ye Olde Web App
Backend 
Ruby 
Python 
Java 
PHP 
Fat-Client, circa 2011 
Persistence 
Client 
DOM manipulation UX JavaScript 
View layer 
Application 
logic Routing
DOM manipulation UX 
Persistence 
Client 
JavaScript 
Shared 
JavaScript 
View layer 
Application 
logic Routing 
Backend 
Ruby 
Python 
Java 
PHP 
Isomorphic, circa 2013
Shared View Layer
DOM manipulation UX 
Persistence 
Client 
JavaScript 
Shared 
JavaScript 
View layer 
Application 
logic Routing 
Backend 
Ruby 
Python 
Java 
PHP 
Isomorphic, circa 2013
View layer
Markup 
Data presentation 
I18n 
Date, Currency formatting 
URL formatting
Isomorphic Use Cases 
1. “Single Page Apps” that can be fully rendered on 
the server. 
2. Ambitious apps that share logic between client & 
server to accomplish novel things.
Why go to the trouble?
Performance 
Initial pageload speed. 
SEO* 
Crawlable single-page apps. 
Flexibility 
Run code anywhere. 
Maintainability 
Reduce code duplication.
Performance
Client-rendered app 
Download 
skeleton 
HTML 
User sees 
content 
Download 
JavaScript 
Fetch data 
from API 
Evaluate 
JavaScript 
Exacerbated on mobile: high 
latency, low bandwidth
Server-rendered app 
Download 
full 
HTML 
Download 
JavaScript 
User sees 
content 
Evaluate 
JavaScript
Isomorphic JavaScript in the 
Wild
Flickr 
! Yahoo’s Modown libraries 
(successor to Mojito).
Instagram* 
! Facebook’s React library 
in a Django app.
Airbnb Mobile Web 
! Airbnb’s Rendr library, built on 
Backbone and Express.
Asana 
! Entire App runtime synced 
between client & server.
Meteor 
! Realtime app framework.
Isomorphic JavaScript is a 
spectrum
Entire view 
layer and app 
logic shared 
Small bits of 
view layer or 
logic shared
Many 
abstractions 
Few 
abstractions
How to Isomorph
Isomorphic JavaScript can be 
environment agnostic 
or 
shimmed per environment.
Environment 
agnostic 
Does not depend on browser-specific properties 
(window) or server-specific properties 
(process.env, req.cookies).
E X A M P L E 
Handlebars.js 
var template = ! 
'<ul>' ! 
'{{#each posts}}' ! 
' <li>{{title}}</li>' ! 
'{{/each}}' ! 
'</ul>';! 
! 
var templateFn = Handlebars.compile(template);! 
var html = templateFn({posts: posts});
Shimmed per 
environment 
Provide shims for accessing environment-specific 
properties so module can expose a single API. 
window.location.pathname 
vs 
req.path
E X A M P L E 
Superagent 
superagent! 
.get('/api/posts.json')! 
.end(function(res) {! 
console.log(res.status, res.body, res.headers);! 
});
Abstractions
A B S T R ACT I O N 
Cookies 
Client document.cookie =! 
'myCookie=1; Domain=.example.org'; 
Server 
res.setHeader(! 
'Set-Cookie: myCookie=1; ' +! 
'Domain=.example.org'! 
);
A B S T R ACT I O N 
Redirects 
Client 
document.location.href = '/login';! 
! 
window.pushState({}, '', '/login'); 
Server res.redirect('/login');
H AC K T I M E 
Let’s write a module that abstracts the setting of 
cookies, providing the same API for client & server.
H AC K T I M E 
setCookie('myCookie', 'the value'); 
document.cookie = 'myCookie=the%20value'; 
or 
res.setHeader('Set-Cookie: myCookie=the%20value;');
H AC K T I M E 
setCookie('myCookie', 'the value', {! 
path: '/',! 
domain: '.example.org',! 
expires: new Date(2014, 12, 31)! 
}); 
document.cookie =! 
'myCookie=the%20value; Domain=.example.org; ' +! 
'Path=/; Expires=Sat, 31 Jan 2015 05:00:00 GMT';
That looks kinda hard…
NPM & Browserify* to the 
rescue
Browserify* Use CommonJS to require() modules in the 
browser.
Browserify* Package dependencies from node_modules into 
our bundle.
*or Webpack. 
Webpack is like Browserify, but with more bells-and- 
whistles included by default. 
Used by Instagram, Facebook, Yahoo!.
H AC K T I M E 
Caveat: It’s Different on the Server 
app.use(function(req, res, next) {! 
...! 
! next();! 
}); 
! 
setCookie('myCookie', 'the value', {res: res});! 
! 
! 
!
How do we make a shimmed-per-environment module? 
Utilize package.json’s “browser” field.
{! 
"name": "set-cookie",! 
"dependencies": {...}! 
}! 
! 
! 
!
{! 
"name": "set-cookie",! 
"dependencies": {...},! 
"browser": "./lib/client.js"! 
}! 
! 
! 
Swap out the entire implementation.
{! 
"name": "set-cookie",! 
"dependencies": {...},! 
"browser": {! 
"./lib/node.js": "./lib/client.js"! 
}! 
}! 
Swap out specific files.
{! 
"name": "set-cookie",! 
"dependencies": {...},! 
"browser": {! 
"./lib/node.js": "./lib/client.js",! 
"cookie": "cookie-browser"! 
}! 
} 
Swap out dependencies.
Let’s build `set-cookie`. 
https://github.com/spikebrehm/set-cookie
Module 
structure 
.! 
"## index.js! 
"## lib! 
$ %## setter! 
$ "## index.js! 
$ %## client.js! 
"## node_modules! 
$ %## cookie
// ./index.js! 
! 
var cookie = require('cookie');! 
var setter = require('./lib/setter');! 
! 
module.exports = function(name, value, options) {! 
var cookieStr = cookie.serialize(name, value, options);! 
setter(cookieStr, options);! 
};
// ./lib/setter/index.js! 
! 
module.exports = function setter(cookieStr, options) {! 
var res = options && options.res;! 
! 
if (!res)! 
throw new Error('Must specify `res` ' +! 
'when setting cookie.’);! 
! 
res.setHeader('Set-Cookie', cookieStr);! 
};
// ./lib/setter/client.js! 
! 
module.exports = function setter(cookieStr) {! 
document.cookie = cookieStr;! 
};
// ./package.json! 
! 
{! 
"name": "set-cookie",! 
"dependencies": {! 
"cookie": "^0.1.2"! 
},! 
"browser": {! 
"./lib/setter/index.js": "./lib/setter/client.js"! 
}! 
}
// ./index.js! 
! 
var cookie = require('cookie');! 
var setter = require('./lib/setter');! 
! 
module.exports = function(name, value, options) {! 
var cookieStr = cookie.serialize(name, value, options);! 
setter(cookieStr, options);! 
};
Projects of Note
React 
Reactive UI component library from Facebook. 
Designed from the ground up to support isomorphic rendering. 
http://facebook.github.io/react/ 
var UserProfile = React.createClass({ 
render: function() { 
return <div> 
<img src={this.props.user.thumbnailUrl} /> 
<h3>{this.props.user.name}</h3> 
</div>; 
} 
}); 
React.render(<UserProfile user={user} />, mountNode);
React 
Reactive UI component library from Facebook. 
Designed from the ground up to support isomorphic rendering. 
http://facebook.github.io/react/ 
var UserProfile = React.createClass({ 
render: function() { 
return <div> 
<img src={this.props.user.thumbnailUrl} /> 
<h3>{this.props.user.name}</h3> 
</div>; 
} 
}); 
React.render(<UserProfile user={user} />, mountNode);
React 
Reactive UI component library from Facebook. 
Designed from the ground up to support isomorphic rendering. 
http://facebook.github.io/react/ 
var UserProfile = React.createClass({ 
render: function() { 
return <div> 
<img src={this.props.user.thumbnailUrl} /> 
<h3>{this.props.user.name}</h3> 
</div>; 
} 
}); 
var html = React.renderToString(<UserProfile user={user} />);
Fluxible 
Yahoo’s isomorphic Flux implementation: Dispatchr, Fetchr, Routr. 
Provides a way to “dehydrate” server state and “rehydrate” on client. 
https://github.com/yahoo/flux-examples
Isobuild 
Meteor’s build system for isomorphic apps. 
Like Browserify & Webpack, uses static analysis to compute 
dependencies. Can target client, server, Android, or iOS. 
https://www.meteor.com/isobuild 
if (Meteor.isClient) { 
// counter starts at 0 
Session.setDefault("counter", 0); 
Template.hello.events({ 
'click button': function () { 
// increment the counter when button is clicked 
Session.set("counter", Session.get("counter") + 1); 
} 
}); 
} 
if (Meteor.isServer) { 
Meteor.startup(function () { 
// code to run on server at startup 
}); 
}
Isobuild 
Meteor’s build system for isomorphic apps. 
Like Browserify & Webpack, uses static analysis to compute 
dependencies. Can target client, server, Android, or iOS. 
https://www.meteor.com/isobuild 
if (Meteor.isClient) { 
// counter starts at 0 
Session.setDefault("counter", 0); 
Template.hello.events({ 
'click button': function () { 
// increment the counter when button is clicked 
Session.set("counter", Session.get("counter") + 1); 
} 
}); 
} 
if (Meteor.isServer) { 
Meteor.startup(function () { 
// code to run on server at startup 
}); 
}
isomorphic-tutorial 
Small sample isomorphic app, written from scratch using Handlebars/ 
React, Director (routing), and Superagent (API requests). 
https://github.com/spikebrehm/isomorphic-tutorial 
// app/routes.js 
var apiClient = require('./api_client'); 
module.exports = function(match) { 
match('/posts', function(callback) { 
apiClient.get('/posts.json', function(err, res) { 
if (err) return callback(err); 
var posts = res.body; 
callback(null, 'posts', {posts: posts}); 
}); 
}); 
};
isomorphic-tutorial 
Small sample isomorphic app, written from scratch using Handlebars/ 
React, Director (routing), and Superagent (API requests). 
https://github.com/spikebrehm/isomorphic-tutorial 
<h1>Posts</h1> 
<ul> 
{{#each posts}} 
<li><a href="/posts/{{id}}">{{title}}</a></li> 
{{/each}} 
</ul>
Thanks! 
More resources available at 
http://spike.technology 
! 
@spikebrehm 
@AirbnbNerds

More Related Content

What's hot

Getting Started with HTML 5 Web workers
Getting Started with HTML 5 Web workersGetting Started with HTML 5 Web workers
Getting Started with HTML 5 Web workersFlumes
 
Node, express & sails
Node, express & sailsNode, express & sails
Node, express & sailsBrian Shannon
 
Service Worker 201 (en)
Service Worker 201 (en)Service Worker 201 (en)
Service Worker 201 (en)Chang W. Doh
 
Workshop Intro: FrontEnd General Overview
Workshop Intro: FrontEnd General OverviewWorkshop Intro: FrontEnd General Overview
Workshop Intro: FrontEnd General OverviewVisual Engineering
 
Packing it all: JavaScript module bundling from 2000 to now
Packing it all: JavaScript module bundling from 2000 to nowPacking it all: JavaScript module bundling from 2000 to now
Packing it all: JavaScript module bundling from 2000 to nowDerek Willian Stavis
 
JavaScript Dependencies, Modules & Browserify
JavaScript Dependencies, Modules & BrowserifyJavaScript Dependencies, Modules & Browserify
JavaScript Dependencies, Modules & BrowserifyJohan Nilsson
 
Isomorphic web application
Isomorphic web applicationIsomorphic web application
Isomorphic web applicationOliver N
 
WordPress as a Platform - talk to Bristol Open Source Meetup, 2014-12-08
WordPress as a Platform - talk to Bristol Open Source Meetup, 2014-12-08WordPress as a Platform - talk to Bristol Open Source Meetup, 2014-12-08
WordPress as a Platform - talk to Bristol Open Source Meetup, 2014-12-08Tim Stephenson
 
NodeWay in my project & sails.js
NodeWay in my project & sails.jsNodeWay in my project & sails.js
NodeWay in my project & sails.jsDmytro Ovcharenko
 
Grunt.js and Yeoman, Continous Integration
Grunt.js and Yeoman, Continous IntegrationGrunt.js and Yeoman, Continous Integration
Grunt.js and Yeoman, Continous IntegrationDavid Amend
 
Avoiding Common Pitfalls in Ember.js
Avoiding Common Pitfalls in Ember.jsAvoiding Common Pitfalls in Ember.js
Avoiding Common Pitfalls in Ember.jsAlex Speller
 
Webpack Tutorial, Uppsala JS
Webpack Tutorial, Uppsala JSWebpack Tutorial, Uppsala JS
Webpack Tutorial, Uppsala JSEmil Öberg
 

What's hot (20)

Getting Started with HTML 5 Web workers
Getting Started with HTML 5 Web workersGetting Started with HTML 5 Web workers
Getting Started with HTML 5 Web workers
 
Node, express & sails
Node, express & sailsNode, express & sails
Node, express & sails
 
Web workers
Web workersWeb workers
Web workers
 
Service Worker 201 (en)
Service Worker 201 (en)Service Worker 201 (en)
Service Worker 201 (en)
 
Browserify
BrowserifyBrowserify
Browserify
 
JavaScript Web Workers
JavaScript Web WorkersJavaScript Web Workers
JavaScript Web Workers
 
Workshop Intro: FrontEnd General Overview
Workshop Intro: FrontEnd General OverviewWorkshop Intro: FrontEnd General Overview
Workshop Intro: FrontEnd General Overview
 
Sails.js Intro
Sails.js IntroSails.js Intro
Sails.js Intro
 
Packing it all: JavaScript module bundling from 2000 to now
Packing it all: JavaScript module bundling from 2000 to nowPacking it all: JavaScript module bundling from 2000 to now
Packing it all: JavaScript module bundling from 2000 to now
 
JavaScript Dependencies, Modules & Browserify
JavaScript Dependencies, Modules & BrowserifyJavaScript Dependencies, Modules & Browserify
JavaScript Dependencies, Modules & Browserify
 
Isomorphic web application
Isomorphic web applicationIsomorphic web application
Isomorphic web application
 
WordPress as a Platform - talk to Bristol Open Source Meetup, 2014-12-08
WordPress as a Platform - talk to Bristol Open Source Meetup, 2014-12-08WordPress as a Platform - talk to Bristol Open Source Meetup, 2014-12-08
WordPress as a Platform - talk to Bristol Open Source Meetup, 2014-12-08
 
NodeWay in my project & sails.js
NodeWay in my project & sails.jsNodeWay in my project & sails.js
NodeWay in my project & sails.js
 
An Intro into webpack
An Intro into webpackAn Intro into webpack
An Intro into webpack
 
Webpack
WebpackWebpack
Webpack
 
Webpack DevTalk
Webpack DevTalkWebpack DevTalk
Webpack DevTalk
 
Web Workers
Web WorkersWeb Workers
Web Workers
 
Grunt.js and Yeoman, Continous Integration
Grunt.js and Yeoman, Continous IntegrationGrunt.js and Yeoman, Continous Integration
Grunt.js and Yeoman, Continous Integration
 
Avoiding Common Pitfalls in Ember.js
Avoiding Common Pitfalls in Ember.jsAvoiding Common Pitfalls in Ember.js
Avoiding Common Pitfalls in Ember.js
 
Webpack Tutorial, Uppsala JS
Webpack Tutorial, Uppsala JSWebpack Tutorial, Uppsala JS
Webpack Tutorial, Uppsala JS
 

Similar to Building Isomorphic Apps (JSConf.Asia 2014)

Web APIs & Apps - Mozilla
Web APIs & Apps - MozillaWeb APIs & Apps - Mozilla
Web APIs & Apps - MozillaRobert Nyman
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...Fabio Franzini
 
从小书签到浏览器扩展的应用
从小书签到浏览器扩展的应用从小书签到浏览器扩展的应用
从小书签到浏览器扩展的应用Alipay
 
Intro to node.js - Ran Mizrahi (27/8/2014)
Intro to node.js - Ran Mizrahi (27/8/2014)Intro to node.js - Ran Mizrahi (27/8/2014)
Intro to node.js - Ran Mizrahi (27/8/2014)Ran Mizrahi
 
Intro to node.js - Ran Mizrahi (28/8/14)
Intro to node.js - Ran Mizrahi (28/8/14)Intro to node.js - Ran Mizrahi (28/8/14)
Intro to node.js - Ran Mizrahi (28/8/14)Ran Mizrahi
 
Html5 and beyond the next generation of mobile web applications - Touch Tou...
Html5 and beyond   the next generation of mobile web applications - Touch Tou...Html5 and beyond   the next generation of mobile web applications - Touch Tou...
Html5 and beyond the next generation of mobile web applications - Touch Tou...RIA RUI Society
 
soft-shake.ch - Hands on Node.js
soft-shake.ch - Hands on Node.jssoft-shake.ch - Hands on Node.js
soft-shake.ch - Hands on Node.jssoft-shake.ch
 
A Story about AngularJS modularization development
A Story about AngularJS modularization developmentA Story about AngularJS modularization development
A Story about AngularJS modularization developmentJohannes Weber
 
Running Vue Storefront in production (PWA Magento webshop)
Running Vue Storefront in production (PWA Magento webshop)Running Vue Storefront in production (PWA Magento webshop)
Running Vue Storefront in production (PWA Magento webshop)Vendic Magento, PWA & Marketing
 
Building Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJSBuilding Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJSAntonio Peric-Mazar
 
Event-driven IO server-side JavaScript environment based on V8 Engine
Event-driven IO server-side JavaScript environment based on V8 EngineEvent-driven IO server-side JavaScript environment based on V8 Engine
Event-driven IO server-side JavaScript environment based on V8 EngineRicardo Silva
 
Mozilla Web Apps - Super-VanJS
Mozilla Web Apps - Super-VanJSMozilla Web Apps - Super-VanJS
Mozilla Web Apps - Super-VanJSRobert Nyman
 
MeasureCamp IX (London) - 10 JavaScript Concepts for web analysts
MeasureCamp IX (London) - 10 JavaScript Concepts for web analystsMeasureCamp IX (London) - 10 JavaScript Concepts for web analysts
MeasureCamp IX (London) - 10 JavaScript Concepts for web analystsSimo Ahava
 
Refactoring Large Web Applications with Backbone.js
Refactoring Large Web Applications with Backbone.jsRefactoring Large Web Applications with Backbone.js
Refactoring Large Web Applications with Backbone.jsStacy London
 
Refactor Large applications with Backbone
Refactor Large applications with BackboneRefactor Large applications with Backbone
Refactor Large applications with BackboneColdFusionConference
 
Refactor Large apps with Backbone
Refactor Large apps with BackboneRefactor Large apps with Backbone
Refactor Large apps with BackbonedevObjective
 
Vaadin 7 CN
Vaadin 7 CNVaadin 7 CN
Vaadin 7 CNjojule
 

Similar to Building Isomorphic Apps (JSConf.Asia 2014) (20)

ParisJS #10 : RequireJS
ParisJS #10 : RequireJSParisJS #10 : RequireJS
ParisJS #10 : RequireJS
 
Web APIs & Apps - Mozilla
Web APIs & Apps - MozillaWeb APIs & Apps - Mozilla
Web APIs & Apps - Mozilla
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
 
从小书签到浏览器扩展的应用
从小书签到浏览器扩展的应用从小书签到浏览器扩展的应用
从小书签到浏览器扩展的应用
 
Intro to node.js - Ran Mizrahi (27/8/2014)
Intro to node.js - Ran Mizrahi (27/8/2014)Intro to node.js - Ran Mizrahi (27/8/2014)
Intro to node.js - Ran Mizrahi (27/8/2014)
 
Intro to node.js - Ran Mizrahi (28/8/14)
Intro to node.js - Ran Mizrahi (28/8/14)Intro to node.js - Ran Mizrahi (28/8/14)
Intro to node.js - Ran Mizrahi (28/8/14)
 
Html5 and beyond the next generation of mobile web applications - Touch Tou...
Html5 and beyond   the next generation of mobile web applications - Touch Tou...Html5 and beyond   the next generation of mobile web applications - Touch Tou...
Html5 and beyond the next generation of mobile web applications - Touch Tou...
 
soft-shake.ch - Hands on Node.js
soft-shake.ch - Hands on Node.jssoft-shake.ch - Hands on Node.js
soft-shake.ch - Hands on Node.js
 
A Story about AngularJS modularization development
A Story about AngularJS modularization developmentA Story about AngularJS modularization development
A Story about AngularJS modularization development
 
Running Vue Storefront in production (PWA Magento webshop)
Running Vue Storefront in production (PWA Magento webshop)Running Vue Storefront in production (PWA Magento webshop)
Running Vue Storefront in production (PWA Magento webshop)
 
Building Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJSBuilding Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJS
 
Event-driven IO server-side JavaScript environment based on V8 Engine
Event-driven IO server-side JavaScript environment based on V8 EngineEvent-driven IO server-side JavaScript environment based on V8 Engine
Event-driven IO server-side JavaScript environment based on V8 Engine
 
Mozilla Web Apps - Super-VanJS
Mozilla Web Apps - Super-VanJSMozilla Web Apps - Super-VanJS
Mozilla Web Apps - Super-VanJS
 
Sanjeev ghai 12
Sanjeev ghai 12Sanjeev ghai 12
Sanjeev ghai 12
 
Symfony2 and AngularJS
Symfony2 and AngularJSSymfony2 and AngularJS
Symfony2 and AngularJS
 
MeasureCamp IX (London) - 10 JavaScript Concepts for web analysts
MeasureCamp IX (London) - 10 JavaScript Concepts for web analystsMeasureCamp IX (London) - 10 JavaScript Concepts for web analysts
MeasureCamp IX (London) - 10 JavaScript Concepts for web analysts
 
Refactoring Large Web Applications with Backbone.js
Refactoring Large Web Applications with Backbone.jsRefactoring Large Web Applications with Backbone.js
Refactoring Large Web Applications with Backbone.js
 
Refactor Large applications with Backbone
Refactor Large applications with BackboneRefactor Large applications with Backbone
Refactor Large applications with Backbone
 
Refactor Large apps with Backbone
Refactor Large apps with BackboneRefactor Large apps with Backbone
Refactor Large apps with Backbone
 
Vaadin 7 CN
Vaadin 7 CNVaadin 7 CN
Vaadin 7 CN
 

Recently uploaded

SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentationphoebematthew05
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 

Recently uploaded (20)

SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentation
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 

Building Isomorphic Apps (JSConf.Asia 2014)

  • 2. Spike Brehm ____________________________ @spikebrehm @AirbnbNerds
  • 3. 1. Why Isomorphic JavaScript 2. Isomorphic in the Wild 3. How to Isomorph
  • 5. What is Isomorphic JavaScript?
  • 6. JavaScript code that can be shared between environments.
  • 9. Persistence Client DOM manipulation UX JavaScript View layer Application logic Routing Backend Ruby Python Java PHP Ye Olde Web App
  • 10. Backend Ruby Python Java PHP Fat-Client, circa 2011 Persistence Client DOM manipulation UX JavaScript View layer Application logic Routing
  • 11. DOM manipulation UX Persistence Client JavaScript Shared JavaScript View layer Application logic Routing Backend Ruby Python Java PHP Isomorphic, circa 2013
  • 13. DOM manipulation UX Persistence Client JavaScript Shared JavaScript View layer Application logic Routing Backend Ruby Python Java PHP Isomorphic, circa 2013
  • 15. Markup Data presentation I18n Date, Currency formatting URL formatting
  • 16. Isomorphic Use Cases 1. “Single Page Apps” that can be fully rendered on the server. 2. Ambitious apps that share logic between client & server to accomplish novel things.
  • 17. Why go to the trouble?
  • 18. Performance Initial pageload speed. SEO* Crawlable single-page apps. Flexibility Run code anywhere. Maintainability Reduce code duplication.
  • 20. Client-rendered app Download skeleton HTML User sees content Download JavaScript Fetch data from API Evaluate JavaScript Exacerbated on mobile: high latency, low bandwidth
  • 21. Server-rendered app Download full HTML Download JavaScript User sees content Evaluate JavaScript
  • 23. Flickr ! Yahoo’s Modown libraries (successor to Mojito).
  • 24. Instagram* ! Facebook’s React library in a Django app.
  • 25. Airbnb Mobile Web ! Airbnb’s Rendr library, built on Backbone and Express.
  • 26. Asana ! Entire App runtime synced between client & server.
  • 27. Meteor ! Realtime app framework.
  • 29. Entire view layer and app logic shared Small bits of view layer or logic shared
  • 30. Many abstractions Few abstractions
  • 32. Isomorphic JavaScript can be environment agnostic or shimmed per environment.
  • 33. Environment agnostic Does not depend on browser-specific properties (window) or server-specific properties (process.env, req.cookies).
  • 34. E X A M P L E Handlebars.js var template = ! '<ul>' ! '{{#each posts}}' ! ' <li>{{title}}</li>' ! '{{/each}}' ! '</ul>';! ! var templateFn = Handlebars.compile(template);! var html = templateFn({posts: posts});
  • 35. Shimmed per environment Provide shims for accessing environment-specific properties so module can expose a single API. window.location.pathname vs req.path
  • 36. E X A M P L E Superagent superagent! .get('/api/posts.json')! .end(function(res) {! console.log(res.status, res.body, res.headers);! });
  • 38. A B S T R ACT I O N Cookies Client document.cookie =! 'myCookie=1; Domain=.example.org'; Server res.setHeader(! 'Set-Cookie: myCookie=1; ' +! 'Domain=.example.org'! );
  • 39. A B S T R ACT I O N Redirects Client document.location.href = '/login';! ! window.pushState({}, '', '/login'); Server res.redirect('/login');
  • 40. H AC K T I M E Let’s write a module that abstracts the setting of cookies, providing the same API for client & server.
  • 41. H AC K T I M E setCookie('myCookie', 'the value'); document.cookie = 'myCookie=the%20value'; or res.setHeader('Set-Cookie: myCookie=the%20value;');
  • 42. H AC K T I M E setCookie('myCookie', 'the value', {! path: '/',! domain: '.example.org',! expires: new Date(2014, 12, 31)! }); document.cookie =! 'myCookie=the%20value; Domain=.example.org; ' +! 'Path=/; Expires=Sat, 31 Jan 2015 05:00:00 GMT';
  • 43. That looks kinda hard…
  • 44.
  • 45. NPM & Browserify* to the rescue
  • 46. Browserify* Use CommonJS to require() modules in the browser.
  • 47. Browserify* Package dependencies from node_modules into our bundle.
  • 48. *or Webpack. Webpack is like Browserify, but with more bells-and- whistles included by default. Used by Instagram, Facebook, Yahoo!.
  • 49. H AC K T I M E Caveat: It’s Different on the Server app.use(function(req, res, next) {! ...! ! next();! }); ! setCookie('myCookie', 'the value', {res: res});! ! ! !
  • 50. How do we make a shimmed-per-environment module? Utilize package.json’s “browser” field.
  • 51. {! "name": "set-cookie",! "dependencies": {...}! }! ! ! !
  • 52. {! "name": "set-cookie",! "dependencies": {...},! "browser": "./lib/client.js"! }! ! ! Swap out the entire implementation.
  • 53. {! "name": "set-cookie",! "dependencies": {...},! "browser": {! "./lib/node.js": "./lib/client.js"! }! }! Swap out specific files.
  • 54. {! "name": "set-cookie",! "dependencies": {...},! "browser": {! "./lib/node.js": "./lib/client.js",! "cookie": "cookie-browser"! }! } Swap out dependencies.
  • 55. Let’s build `set-cookie`. https://github.com/spikebrehm/set-cookie
  • 56. Module structure .! "## index.js! "## lib! $ %## setter! $ "## index.js! $ %## client.js! "## node_modules! $ %## cookie
  • 57. // ./index.js! ! var cookie = require('cookie');! var setter = require('./lib/setter');! ! module.exports = function(name, value, options) {! var cookieStr = cookie.serialize(name, value, options);! setter(cookieStr, options);! };
  • 58. // ./lib/setter/index.js! ! module.exports = function setter(cookieStr, options) {! var res = options && options.res;! ! if (!res)! throw new Error('Must specify `res` ' +! 'when setting cookie.’);! ! res.setHeader('Set-Cookie', cookieStr);! };
  • 59. // ./lib/setter/client.js! ! module.exports = function setter(cookieStr) {! document.cookie = cookieStr;! };
  • 60. // ./package.json! ! {! "name": "set-cookie",! "dependencies": {! "cookie": "^0.1.2"! },! "browser": {! "./lib/setter/index.js": "./lib/setter/client.js"! }! }
  • 61. // ./index.js! ! var cookie = require('cookie');! var setter = require('./lib/setter');! ! module.exports = function(name, value, options) {! var cookieStr = cookie.serialize(name, value, options);! setter(cookieStr, options);! };
  • 63. React Reactive UI component library from Facebook. Designed from the ground up to support isomorphic rendering. http://facebook.github.io/react/ var UserProfile = React.createClass({ render: function() { return <div> <img src={this.props.user.thumbnailUrl} /> <h3>{this.props.user.name}</h3> </div>; } }); React.render(<UserProfile user={user} />, mountNode);
  • 64. React Reactive UI component library from Facebook. Designed from the ground up to support isomorphic rendering. http://facebook.github.io/react/ var UserProfile = React.createClass({ render: function() { return <div> <img src={this.props.user.thumbnailUrl} /> <h3>{this.props.user.name}</h3> </div>; } }); React.render(<UserProfile user={user} />, mountNode);
  • 65. React Reactive UI component library from Facebook. Designed from the ground up to support isomorphic rendering. http://facebook.github.io/react/ var UserProfile = React.createClass({ render: function() { return <div> <img src={this.props.user.thumbnailUrl} /> <h3>{this.props.user.name}</h3> </div>; } }); var html = React.renderToString(<UserProfile user={user} />);
  • 66. Fluxible Yahoo’s isomorphic Flux implementation: Dispatchr, Fetchr, Routr. Provides a way to “dehydrate” server state and “rehydrate” on client. https://github.com/yahoo/flux-examples
  • 67. Isobuild Meteor’s build system for isomorphic apps. Like Browserify & Webpack, uses static analysis to compute dependencies. Can target client, server, Android, or iOS. https://www.meteor.com/isobuild if (Meteor.isClient) { // counter starts at 0 Session.setDefault("counter", 0); Template.hello.events({ 'click button': function () { // increment the counter when button is clicked Session.set("counter", Session.get("counter") + 1); } }); } if (Meteor.isServer) { Meteor.startup(function () { // code to run on server at startup }); }
  • 68. Isobuild Meteor’s build system for isomorphic apps. Like Browserify & Webpack, uses static analysis to compute dependencies. Can target client, server, Android, or iOS. https://www.meteor.com/isobuild if (Meteor.isClient) { // counter starts at 0 Session.setDefault("counter", 0); Template.hello.events({ 'click button': function () { // increment the counter when button is clicked Session.set("counter", Session.get("counter") + 1); } }); } if (Meteor.isServer) { Meteor.startup(function () { // code to run on server at startup }); }
  • 69. isomorphic-tutorial Small sample isomorphic app, written from scratch using Handlebars/ React, Director (routing), and Superagent (API requests). https://github.com/spikebrehm/isomorphic-tutorial // app/routes.js var apiClient = require('./api_client'); module.exports = function(match) { match('/posts', function(callback) { apiClient.get('/posts.json', function(err, res) { if (err) return callback(err); var posts = res.body; callback(null, 'posts', {posts: posts}); }); }); };
  • 70. isomorphic-tutorial Small sample isomorphic app, written from scratch using Handlebars/ React, Director (routing), and Superagent (API requests). https://github.com/spikebrehm/isomorphic-tutorial <h1>Posts</h1> <ul> {{#each posts}} <li><a href="/posts/{{id}}">{{title}}</a></li> {{/each}} </ul>
  • 71. Thanks! More resources available at http://spike.technology ! @spikebrehm @AirbnbNerds