JSConf US 2014: Building Isomorphic Apps

Post on 10-May-2015

2.672 views 0 download

Tags:

description

Slides from Spike Brehm's talk at JSConf US 2014. Topics include the etymology of "Isomorphic JavaScript", examples is isomorphic apps in the wild, reasons behind the growing trend towards isomorphic apps, and how to build an isomorphic module using Browserify & NPM.

Transcript of JSConf US 2014: Building Isomorphic Apps

Building Isomorphic Apps

Spike Brehm @spikebrehm

@spikebrehm @AirbnbNerds

Spike Brehm

Isomorphic JavaScript.

WTF is Isomorphic JavaScript?

JavaScript code that can be shared between environments.

JavaScript code that can be shared between environments.

JavaScript code that can be shared between environments.

JavaScript code that can be shared between environments.

Backend Ruby

Python Java PHP

Node.js

Persistence

Client JavaScript

Shared JavaScript

DOM manipulation UX

View layer Application logic Routing

Etymology of “Isomorphic JavaScript”.

adjective corresponding or similar in form and relations.

i·so·mor·phic

i·so·mor·phicformsame

http://blog.nodejitsu.com/scaling-isomorphic-javascript-code/

“monomorphic” “heteromorphic” “homomorphic” “polymorphic”

You’re using it wrong!

Isomorphic JavaScript in the wild.

! Yahoo’s Modown libraries Flickr

! Yahoo’s Modown libraries Flickr

! Yahoo’s Modown libraries (successor to Mojito).

Flickr

! Facebook’s React library Instagram*

! Facebook’s React library Instagram*

! Facebook’s React library in a Django app.

Instagram*

! Airbnb’s Rendr library, built on Airbnb Mobile

! Airbnb’s Rendr library, built on Airbnb Mobile

! Airbnb’s Rendr library, built on Backbone and Express.

Airbnb Mobile

! Entire App runtime synced Asana

! Entire App runtime synced between client & server.

Asana

! Realtime app framework. Meteor

! Realtime app framework. Meteor

Wy go to the trouble?

Initial pageload speed.Performance

Crawlable single-page apps.SEO*

Reduce code duplication.MaintainabilityRun code anywhere.Flexibility

Isomorphic use cases.

• Templating • I18n • Date & currency formatting • Application logic • Routing • Model validation • API interaction • ...?

Isomorphic use cases.

Isomorphic JavaScript is a spectrum.

Entire view layer and app

logic shared

Small bits of view layer or logic shared

Many abstractions

Few abstractions

View layer shared

Entire app runtime synced between client

& server

Isomorphic JavaScript can be

or shimmed per environment .

environment-agnostic

Does not depend on browser-specific properties (window) or server-specific properties (process.env, req.cookies).

Environment-agnostic

Example: Handlebars.js

var template = ! '<ul>' \! '{{#each posts}}' \! ' <li>{{title}}</li>' \! '{{/each}}' \! '</ul>'!;! !var templateFn = Handlebars.compile(template)! , html = templateFn({posts: posts});

Provide shims for accessing environment-specific properties so module can expose a single API.

window.location.pathnamevs. req.path

Shimmed per environment

Example: Superagent

superagent! .get('/api/posts.json')! .end(function(res) {! if (res.status === 200) {! console.log("Posts:", res.body);! } else {! console.error("Error");! }! });

Abstractions.

Abstraction: User Agent

Client navigator.userAgent

Server req.get('user-agent')

Abstraction: Cookies

Client document.cookie =! 'myCookie=1; Domain=.example.org';

Server res.setHeader(! 'Set-Cookie: myCookie=1; ' +! 'Domain=.example.org'! );

Abstraction: Redirects

Clientdocument.location.href = '/login';!

!window.pushState({}, '', '/login');

Server res.redirect('/login');

How to isomorph.

Let’s write a module that abstracts the setting of cookies, providing the same API for client & server.

setCookie('myCookie', 'the value');

setCookie('myCookie', 'the value');

document.cookie = 'myCookie=the%20value';

or

res.setHeader('Set-Cookie: myCookie=the%20value;');

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';

Eww, that looks hard.

NPM & Browserify to the rescue.

BrowserifyUse CommonJS to require() modules in the browser.

BrowserifyPackage dependencies from node_modules into our bundle.

How do we make a shimmed-per-environment module?Utilize package.json “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);!};

How to isomorph in a nutshell.

@spikebrehm@AirbnbNerds

Thanks!More resources available at

http://spike.technology

@spikebrehm@AirbnbNerds

Thanks!More resources available at

http://spike.technology

We’re hiring!!!We’re hiring!!!We’re hiring!!!We’re hiring!!!We’re hiring!!!We’re hiring!!!