71
Building Isomorphic Apps Spike Brehm @spikebrehm

JSConf US 2014: Building Isomorphic Apps

Embed Size (px)

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.

Citation preview

Page 1: JSConf US 2014: Building Isomorphic Apps

Building Isomorphic Apps

Spike Brehm @spikebrehm

Page 2: JSConf US 2014: Building Isomorphic Apps

@spikebrehm @AirbnbNerds

Spike Brehm

Page 3: JSConf US 2014: Building Isomorphic Apps

Isomorphic JavaScript.

Page 4: JSConf US 2014: Building Isomorphic Apps

WTF is Isomorphic JavaScript?

Page 5: JSConf US 2014: Building Isomorphic Apps

JavaScript code that can be shared between environments.

Page 6: JSConf US 2014: Building Isomorphic Apps

JavaScript code that can be shared between environments.

Page 7: JSConf US 2014: Building Isomorphic Apps

JavaScript code that can be shared between environments.

Page 8: JSConf US 2014: Building Isomorphic Apps

JavaScript code that can be shared between environments.

Page 9: JSConf US 2014: Building Isomorphic Apps

Backend Ruby

Python Java PHP

Node.js

Persistence

Client JavaScript

Shared JavaScript

DOM manipulation UX

View layer Application logic Routing

Page 10: JSConf US 2014: Building Isomorphic Apps

Etymology of “Isomorphic JavaScript”.

Page 11: JSConf US 2014: Building Isomorphic Apps

adjective corresponding or similar in form and relations.

i·so·mor·phic

Page 12: JSConf US 2014: Building Isomorphic Apps

i·so·mor·phicformsame

Page 13: JSConf US 2014: Building Isomorphic Apps

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

Page 14: JSConf US 2014: Building Isomorphic Apps

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

You’re using it wrong!

Page 15: JSConf US 2014: Building Isomorphic Apps
Page 16: JSConf US 2014: Building Isomorphic Apps

Isomorphic JavaScript in the wild.

Page 17: JSConf US 2014: Building Isomorphic Apps

! Yahoo’s Modown libraries Flickr

Page 18: JSConf US 2014: Building Isomorphic Apps

! Yahoo’s Modown libraries Flickr

Page 19: JSConf US 2014: Building Isomorphic Apps

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

Flickr

Page 20: JSConf US 2014: Building Isomorphic Apps

! Facebook’s React library Instagram*

Page 21: JSConf US 2014: Building Isomorphic Apps

! Facebook’s React library Instagram*

Page 22: JSConf US 2014: Building Isomorphic Apps

! Facebook’s React library in a Django app.

Instagram*

Page 23: JSConf US 2014: Building Isomorphic Apps

! Airbnb’s Rendr library, built on Airbnb Mobile

Page 24: JSConf US 2014: Building Isomorphic Apps

! Airbnb’s Rendr library, built on Airbnb Mobile

Page 25: JSConf US 2014: Building Isomorphic Apps

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

Airbnb Mobile

Page 26: JSConf US 2014: Building Isomorphic Apps

! Entire App runtime synced Asana

Page 27: JSConf US 2014: Building Isomorphic Apps

! Entire App runtime synced between client & server.

Asana

Page 28: JSConf US 2014: Building Isomorphic Apps

! Realtime app framework. Meteor

Page 29: JSConf US 2014: Building Isomorphic Apps

! Realtime app framework. Meteor

Page 30: JSConf US 2014: Building Isomorphic Apps

Wy go to the trouble?

Page 31: JSConf US 2014: Building Isomorphic Apps

Initial pageload speed.Performance

Crawlable single-page apps.SEO*

Reduce code duplication.MaintainabilityRun code anywhere.Flexibility

Page 32: JSConf US 2014: Building Isomorphic Apps

Isomorphic use cases.

Page 33: JSConf US 2014: Building Isomorphic Apps

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

Isomorphic use cases.

Page 34: JSConf US 2014: Building Isomorphic Apps

Isomorphic JavaScript is a spectrum.

Page 35: JSConf US 2014: Building Isomorphic Apps

Entire view layer and app

logic shared

Small bits of view layer or logic shared

Page 36: JSConf US 2014: Building Isomorphic Apps

Many abstractions

Few abstractions

Page 37: JSConf US 2014: Building Isomorphic Apps

View layer shared

Entire app runtime synced between client

& server

Page 38: JSConf US 2014: Building Isomorphic Apps

Isomorphic JavaScript can be

or shimmed per environment .

environment-agnostic

Page 39: JSConf US 2014: Building Isomorphic Apps

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

Environment-agnostic

Page 40: JSConf US 2014: Building Isomorphic Apps

Example: Handlebars.js

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

Page 41: JSConf US 2014: Building Isomorphic Apps

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

window.location.pathnamevs. req.path

Shimmed per environment

Page 42: JSConf US 2014: Building Isomorphic Apps

Example: Superagent

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

Page 43: JSConf US 2014: Building Isomorphic Apps

Abstractions.

Page 44: JSConf US 2014: Building Isomorphic Apps

Abstraction: User Agent

Client navigator.userAgent

Server req.get('user-agent')

Page 45: JSConf US 2014: Building Isomorphic Apps

Abstraction: Cookies

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

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

Page 46: JSConf US 2014: Building Isomorphic Apps

Abstraction: Redirects

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

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

Server res.redirect('/login');

Page 47: JSConf US 2014: Building Isomorphic Apps

How to isomorph.

Page 48: JSConf US 2014: Building Isomorphic Apps

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

Page 49: JSConf US 2014: Building Isomorphic Apps

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

Page 50: JSConf US 2014: Building Isomorphic Apps

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

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

or

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

Page 51: JSConf US 2014: Building Isomorphic Apps

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

Page 52: JSConf US 2014: Building Isomorphic Apps

Eww, that looks hard.

Page 53: JSConf US 2014: Building Isomorphic Apps
Page 54: JSConf US 2014: Building Isomorphic Apps

NPM & Browserify to the rescue.

Page 55: JSConf US 2014: Building Isomorphic Apps

BrowserifyUse CommonJS to require() modules in the browser.

Page 56: JSConf US 2014: Building Isomorphic Apps

BrowserifyPackage dependencies from node_modules into our bundle.

Page 57: JSConf US 2014: Building Isomorphic Apps

How do we make a shimmed-per-environment module?Utilize package.json “browser” field.

Page 58: JSConf US 2014: Building Isomorphic Apps

{! "name": "set-cookie",! "dependencies": {...}!}!!!!

Page 59: JSConf US 2014: Building Isomorphic Apps

{! "name": "set-cookie",! "dependencies": {...},! "browser": "./lib/client.js"!}!!!

Swap out the entire implementation.

Page 60: JSConf US 2014: Building Isomorphic Apps

{! "name": "set-cookie",! "dependencies": {...},! "browser": {! "./lib/node.js": "./lib/client.js"! }!}!

Swap out specific files.

Page 61: JSConf US 2014: Building Isomorphic Apps

{! "name": "set-cookie",! "dependencies": {...},! "browser": {! "./lib/node.js": "./lib/client.js",! "cookie": "cookie-browser"! }!}

Swap out dependencies.

Page 62: JSConf US 2014: Building Isomorphic Apps

Let’s build `set-cookie`.https://github.com/spikebrehm/set-cookie

Page 63: JSConf US 2014: Building Isomorphic Apps

Module structure.!"## index.js!"## lib!$   %## setter!$   "## index.js!$   %## client.js!"## node_modules!$   %## cookie

Page 64: JSConf US 2014: Building Isomorphic Apps

// ./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);!};

Page 65: JSConf US 2014: Building Isomorphic Apps

// ./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);!};

Page 66: JSConf US 2014: Building Isomorphic Apps

// ./lib/setter/client.js!!module.exports = function setter(cookieStr) {!  document.cookie = cookieStr;!};

Page 67: JSConf US 2014: Building Isomorphic Apps

// ./package.json!!{! "name": "set-cookie",! "dependencies": {! "cookie": "^0.1.2"! },! "browser": {! "./lib/setter/index.js": "./lib/setter/client.js"! }!}

Page 68: JSConf US 2014: Building Isomorphic Apps

// ./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);!};

Page 69: JSConf US 2014: Building Isomorphic Apps

How to isomorph in a nutshell.

Page 70: JSConf US 2014: Building Isomorphic Apps

@spikebrehm@AirbnbNerds

Thanks!More resources available at

http://spike.technology

Page 71: JSConf US 2014: Building Isomorphic Apps

@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!!!