The Evolution of Airbnb's Frontend

56
The Evolution of Airbnb’s Frontend @spikebrehm

Transcript of The Evolution of Airbnb's Frontend

The Evolution of Airbnb’s Frontend

!

@spikebrehm

Spike Brehm ____________________________

@spikebrehm

!

@AirbnbNerds since 2011

1. A Brief History of airbnb.com 2. Modernizing our JavaScript Stack 3. Airbnb & Isomorphic JavaScript

A Brief History of airbnb.com

! airbedandbreakfast.com 2008

! airbnb.com 2009

! airbnb.com 2012

! airbnb.com 2015

Rails 2.x

MySQL

Vanilla CSS

Prototype.js!2009

Rails 3.x, Java

MySQL, Redis, HDFS, Postgres, DynamoDB

SASS, O2

jQuery, Backbone, Handlebars

!2012

! Bootstrap-inspired CSS frameworkO2

Rails 3.x, Java, Node.js

MySQL, Redis, HDFS, Postgres, DynamoDB, Kafka, RabbitMQ, …

SASS, O2

jQuery, Backbone, Handlebars, React, CommonJS, ES6

!2015

Modernizing our JavaScript Stack

A. JavaScript Libraries

Flight

! Listing management tools

Hitting a Wall with Backbone & Handlebars

Backbone & Handlebars approach falls apart as UI components become more dynamic.

No data binding, so have to either:

1. Re-render whole view when model changes (slow, lose DOM state like focused fields).

2. Drop down to manual DOM manipulation.

Airbnb <3 React

React makes it easier to build & maintain stateful UI components.

React makes it easier to reason about data flow in your app.

B. Asset building

Sprockets

Rails asset pipeline: manages JavaScripts, stylesheets, images, etc.

Written by Ruby devs to solve problems of simple web apps.

JavaScript </3 Sprockets

Doesn’t solve JavaScript dependency management:

1. Local dependencies (application code)

2. External dependencies (third-part libraries)

/* application.js *///= require_tree .

/* application.js */!//= require ./models/listing.js//= require ./collections/listings.js//= require_tree .

What if one file depends on another?

Bad: Order matters Bad: Objects attached to `window` Bad: Implicit dependencies

Local dependencies

$ cp ~/Downloads/backbone.js app/assets/javascripts/vendor/ backbone-1.1.12.js

/* application.js */!//= require vendor/backbone-1.1.12.js...//= require_tree .

What if I want to use Backbone?

Bad: Manually download Bad: Manually versioning Bad: Implicit dependencies

External dependencies

CommonJS & NPM to the rescue

/* collections/listings.js */var Listing = require(‘../models/listing’);!module.exports = ...

Good: Explicit dependencies Good: Don’t worry about ordering Good: Objects not leaked to `window`

Local dependencies

/* collections/listings.js */var Listing = require(‘../models/listing’);var Backbone = require(‘backbone’);!module.exports = Backbone.Collection.extend({ ...});

Good: Central management Good: Explicit dependencies

External dependencies

$ npm install --save [email protected]

Explicit Dependencies

Browserify*

Use CommonJS syntax in client-side modules: `require` and `module.exports`.

Package dependencies from NPM.

Transforms.

* or Webpack

Browserify Transforms

Handlebars var template = require(‘./templates/user.hbs’);!var html = template({name: “Spike”});

es2015 import Header from ‘./Header.jsx’;!const numMonths = 36;!let photos = users.map((user) => user.photo);

Airbnb & Isomorphic JavaScript

JavaScript code that can be shared between environments.

+

Client-side MVC

Client

Server

Your app API

+

Client + server MVC

Server

Client

Your app API

PerformanceInitial pageload speed.

SEO*Crawlable single-page apps.

FlexibilityRun code anywhere.

MaintainabilityReduce code duplication.

Performance

Client-rendered appDownload skeleton HTML

User sees content

Download JavaScript

Fetch data from API

Evaluate JavaScript

Exacerbated on mobile: high latency, low bandwidth

Server-rendered appDownload

full HTML

Download JavaScript

User sees content

Evaluate JavaScript

Rendr

Moving Away from Rendr at Airbnb

It was revolutionary to share code between client and server using Node.js…

10%

90%

Rails Node.js

…but too hard to share code between server and server — between Rails and Node.js.

Long tail of features to rewrite in JavaScript:

1. CSRF tokens 2. Custom headers, i.e.

CDN 3. Middleware 4. Application code

Do we rewrite everything in Node.js?

The single worst strategic mistake that any software company can make: !Rewrite the code from scratch.

Joel Spolsky

A New Approach to Isomorphic JavaScript at

Airbnb

Browser.

Rails.

App.jsx

Fetch JSON data

Node.js.App.jsx

Mystique: Node.js rendering service

for React components

Allows us to render React components on the server from within Rails.

Built on Iso, tiny utility for isomorphic bootstrapping of React components. https://github.com/goatslacker/iso

! https://www.airbnb.com/getaways/san-francisco A/B testing now

Thanks! !

!

@spikebrehm @AirbnbNerds