real world single page app - a knockout case study

74
REAL WORLD SPA A Knockout Case Study Cory House @housecor .com

Upload: housecor

Post on 22-Nov-2014

200 views

Category:

Software


1 download

DESCRIPTION

This presentation explores lessons learned from building a highly complex single page application that's used by 100's of automotive dealerships to finance and sell cars. We’ll walk through how to manage a pure client-side application with 1000’s of lines of custom JavaScript and review how Web API, Knockout, Durandal, RequireJS, KendoUI, and surprisingly little jQuery can join forces to make the browser sing. You’ll gain a clear understanding of when a single page app approach makes sense and learn how to pragmatically divide responsibilities between the client and server. This session will give you an appreciation for how far you can push ultra-responsive client-side rendering in the real-world.

TRANSCRIPT

Page 1: Real World Single Page App - A Knockout Case Study

REAL WORLD SPAA Knockout Case Study

Cory House @housecor

.com

Page 2: Real World Single Page App - A Knockout Case Study

Learn From My Mistakes

Page 3: Real World Single Page App - A Knockout Case Study

Knowledge Survey

Have you built a SPA?

Know Ember, Angular, Backbone?

Worked with Knockout, Durandal, Require, Fiddler, AJAX?

Page 4: Real World Single Page App - A Knockout Case Study

Here’s the Focus1. App walk-through

2. 10 Lessons Learned

3. Does this even make sense?

Page 5: Real World Single Page App - A Knockout Case Study

What monthly payment would you

like?

Page 6: Real World Single Page App - A Knockout Case Study

App Demo

Page 7: Real World Single Page App - A Knockout Case Study

New App: Two Goals

1. Cross Platform

2. Speed

Page 8: Real World Single Page App - A Knockout Case Study

10Lessons Learned

Page 9: Real World Single Page App - A Knockout Case Study

1Decisions are Hard.And we were wrong. A lot.

Page 10: Real World Single Page App - A Knockout Case Study

Sea of Decisions

Page 11: Real World Single Page App - A Knockout Case Study

but…

Page 12: Real World Single Page App - A Knockout Case Study
Page 13: Real World Single Page App - A Knockout Case Study

LightUnopinionatedLibrary

RichOpinionatedFramework

Page 14: Real World Single Page App - A Knockout Case Study

LightUnopinionatedLibrary

RichOpinionatedFramework

Page 15: Real World Single Page App - A Knockout Case Study

Pick a Language?!

Page 16: Real World Single Page App - A Knockout Case Study

Service Layer

WebAPI

Page 17: Real World Single Page App - A Knockout Case Study

And Pick a Promise Library…

Q RSVP

Bluebird jQuery

Page 18: Real World Single Page App - A Knockout Case Study

And a Testing Framework…

Page 19: Real World Single Page App - A Knockout Case Study

Utility Libraries

Page 20: Real World Single Page App - A Knockout Case Study

Data

Page 21: Real World Single Page App - A Knockout Case Study

Network TransportAJAX

Go 2-way:

WebSocket

AJAX Long-polling

Adobe® Flash® Socket

AJAX multipart streaming

Forever Iframe

JSONP Polling

Or punt:

Page 22: Real World Single Page App - A Knockout Case Study

NoSQL?

Page 23: Real World Single Page App - A Knockout Case Study

2Unobtrusive JSDead?

Page 25: Real World Single Page App - A Knockout Case Study

Unobtrusive JavaScript Movement: Dead?

1999 Inline

2007 Unobtrusive

Knockout

Angular

2013 Databinding

Page 26: Real World Single Page App - A Knockout Case Study

Databinding Advantages

Discoverability

Clarity

Less Code

Page 27: Real World Single Page App - A Knockout Case Study

Consider the Maintenance Programmer

Physically separating concerns that are logically intertwined without an explicit interface obfuscates rather than aids understanding.

Page 28: Real World Single Page App - A Knockout Case Study

3Bundle & MinifyMaybe not?

Page 29: Real World Single Page App - A Knockout Case Study

Heavy Load

93 JS

19 HTML

5 CSS

11 Images

----------------

132 HTTP requests?!

Page 30: Real World Single Page App - A Knockout Case Study

The Full SPA

93 JS files

53 viewmodels

9 libraries

39 Popup windows

56 HTML files

94 RESTful endpoints

Page 31: Real World Single Page App - A Knockout Case Study

Why Minify and Bundle?

1. Reduce HTTP requests to reduce load on server

2. Speed page load

3. Obfuscate code

Page 32: Real World Single Page App - A Knockout Case Study

Why Not Minify and Bundle?

1. Prod no longer matches dev

2. Risk of introducing obscure bugs

3. Debugging in prod is more complex

4. Complexity (and thus risk) must be justified

Page 33: Real World Single Page App - A Knockout Case Study

How’s Performance? It Depends.

Chrome IE8

Empty cache 6 13

Warm cache 3 3

Load first deal 1 2

Load second deal 1 2

Recalculate payment

1 2

To nearest second

Page 34: Real World Single Page App - A Knockout Case Study

4We’re blind to errors!That’s malpractice.

Page 35: Real World Single Page App - A Knockout Case Study
Page 36: Real World Single Page App - A Knockout Case Study

‘Twas Blind, but Now I See…

Page 37: Real World Single Page App - A Knockout Case Study

5Fast in Chrome?Meaningless.

Page 38: Real World Single Page App - A Knockout Case Study

Old IE, The Laggard

10x slower 5x slower

Page 40: Real World Single Page App - A Knockout Case Study

DOM Weight

Traditional

Duplicate elements rendered

Client-side

Single template

Page 42: Real World Single Page App - A Knockout Case Study

6Unix or Windows Mindset?No right answer.

Page 43: Real World Single Page App - A Knockout Case Study

Our Tech Stack

Page 44: Real World Single Page App - A Knockout Case Study

WebAPIORMLiteMSTest

KnockoutJS

Durandal

RequireJS

KendoUIKnockout.Mapping & Knockout-

KendoToastr

jQuery Q.js QUnit

Our Stack

Page 45: Real World Single Page App - A Knockout Case Study

Why Use Knockoutwith Durandal?

14% of our customers :_(

Page 46: Real World Single Page App - A Knockout Case Study

1. Convention

2. Composition

<div data-bind=“compose: ‘viewmodels/vehicle’></div><!-- ko compose: ‘viewmodels/vehicle’ --><!-- /ko -->

3. Routing

Page 47: Real World Single Page App - A Knockout Case Study

A Torrid Love Affair…

Page 48: Real World Single Page App - A Knockout Case Study
Page 49: Real World Single Page App - A Knockout Case Study
Page 50: Real World Single Page App - A Knockout Case Study
Page 51: Real World Single Page App - A Knockout Case Study

WebAPIORMLiteMSTest

KnockoutJS

Durandal

RequireJS

KendoUIKnockout.Mapping & Knockout-

KendoToastr

jQuery Q.js QUnit

Our Stack

Page 52: Real World Single Page App - A Knockout Case Study

WebAPIORMLiteMSTest

AngularJS

KendoUI

If We Used AngularJS instead…

Page 53: Real World Single Page App - A Knockout Case Study

7TypeScript or TestOr refactor at your own risk

Page 54: Real World Single Page App - A Knockout Case Study

My Awesome JS Refactoring Tool

Page 55: Real World Single Page App - A Knockout Case Study

And a Testing Framework…

Page 56: Real World Single Page App - A Knockout Case Study

What I’m testing:Service endpointsBusiness logicThat the data displays (implied)

Page 57: Real World Single Page App - A Knockout Case Study

8Architect Your JS like C#.DAL, BLL, Presentation…

Page 58: Real World Single Page App - A Knockout Case Study

Create a Client-Side “DAL”

JSON.stringify

Centralized service layer

Single wrapper around $.ajax

View

ViewModel

Service

AJAX service

Page 59: Real World Single Page App - A Knockout Case Study

Keep Your Viewmodels Thin

Create Business objects!

Instantiate them in your viewmodels

A 1,000+ line viewmodel is as smelly as a 1,000 class.

Page 60: Real World Single Page App - A Knockout Case Study

Avoid here.

Where Should I Put the Business Logic?

Prefer Here

Page 61: Real World Single Page App - A Knockout Case Study

9Config Object PatternDynamism belongs in JSON

Page 62: Real World Single Page App - A Knockout Case Study

JavaScript Configuration Object PatternJavaScript belongs in static .js files

Not strings in C#, Java, etc.

1 language per file

Inject dynamism via JSON from the server.

Page 63: Real World Single Page App - A Knockout Case Study

JavaScript Configuration Object Pattern

Page 64: Real World Single Page App - A Knockout Case Study

Config Object Pattern: A JustificationSeparation of concerns 

Caching 

Minimizes string parsing overhead

Code coloring 

Syntax checking

Reusable

Reduced payload 

Less abstraction

bitnative.com/2013/10/06/javascript-configuration-object-pattern/

Page 65: Real World Single Page App - A Knockout Case Study

1 Manage DependenciesKeep the global namespace clear.0

Page 66: Real World Single Page App - A Knockout Case Study

RequireJS

Utilizes AMD pattern

Dynamically load JS

Inject dependencies

Watch for circular dependencies

Page 67: Real World Single Page App - A Knockout Case Study

1Stay DRYDon’t repeat viewmodels on server & client1

Page 68: Real World Single Page App - A Knockout Case Study

var firstName = ko.observable(user.firstName);

var middleName = ko.observable(user.middleName);

var lastName = ko.observable(user.lastName);

Instead:

var user = ko.mapping.fromJS(user);

Page 69: Real World Single Page App - A Knockout Case Study

How Do I Stay DRY?

Use KO mapping plugin

Inject nullos via the Configuration Object Pattern

Ko.utils.

Page 70: Real World Single Page App - A Knockout Case Study

Does This Even Make Sense?

Page 71: Real World Single Page App - A Knockout Case Study

Why not?

Proprietary business logic

Low interactivity

Slower page load

Page is rarely called

Complex – Too many choices!

Debugging pain Runtime errors Cryptic One mistake and nothing loads

Page 72: Real World Single Page App - A Knockout Case Study

Why?

Responsive

Rich Interactivity

Separation of concerns

Efficient

Simple - Less abstraction Debugging No compile wait

Faster page load

Page 73: Real World Single Page App - A Knockout Case Study
Page 74: Real World Single Page App - A Knockout Case Study

SPA Experience Complete

Cory House

bitnative.com

@housecor

spkr8.com/t/35431