Taking your “web” app to places you never expected - Ember Fest 2014

Preview:

DESCRIPTION

Presentation slides for Ember Fest 2014. Gives overview of steps needed to take an ember app offline.

Citation preview

IAEA International Atomic Energy Agency

Taking Your “Web” App To places you never expected

Garth Williams @williamsgarth

IAEA

Introduction

IAEA Headquarters in Vienna http://iaea.org

IAEA

Background

• The IAEA inspects nuclear facilities all over the world

• The IAEA is currently modernising a number of legacy applications

• Our inspectors need to collect and store data where no network connection is guaranteed or even allowed

• Our team is writing the next version of software for facility inspections

IAEA

Let’s use WPF?

• A desktop app is the logical choice, right?

• Organisation standards are based on Microsoft technologies

• So Windows Presentation Foundation must be the right choice?

• (Oh, by the way, we may need to support tablets in 2015)

IAEA

Why HTML(5) is better

• HTML5 includes all the building blocks for offline apps

• Web apps don’t need to be installed

• HTML is portable

IAEA

Ember is a good fit

• Full stack framework

• Well suited to larger projects:

• Ember offers familiar conventions

• Ember encourages consistency and structure through the use of components, ember data, stateful routing, etc…

• Compiles down to one or two js distributables

IAEA

Taking ember offline (manifest.appcache)

• Use a manifest file • Lists all resources needed when offline

• CSS, Fonts, Images, JavaScript, HTML, etc… • Referenced in your html tag

<!DOCTYPE*html>*<html*manifest=“/manifest.appcache”>***…*</html>

IAEA

Taking ember offline (manifest.appcache)

CACHE*MANIFEST*#-Version-1.0.0-!

CACHE:*/js/app.js*/css/app.css*/images/logo.png*/fonts/fontawesomeJwebfont.woff*/404.html*!

NETWORK:*/api*!

FALLBACK:*/*/404.html

IAEA

What about my beautiful client side URLs?

• Single page apps used to use # for client side routing

• For an app is located at

• https://stunningapp.com/

• When the client navigates to entity 5 then we can have

• https://stunningapp.com/#/entity/5

IAEA

What about my beautiful client side URLs?

• But now I’m using push state, how can this dynamic url be available offline?

• https://stunningapp.com/entity/5/

IAEA

What about my beautiful client side URLs?

• Use the FALLBACK section of the manifest file

CACHE*MANIFEST*!

CACHE:*/*!

FALLBACK:*#-normal-fallback:-/-/404.html-#-Support-Push-State-/*/

• Any page not stored locally will return the cached root page

IAEA

Caching hell & double reloads

• First time a browser visits your app:

1. HTML is downloaded

2. Manifest is detected and downloaded

3. Resources listed in manifest are downloaded and stored

IAEA

Caching hell & double reloads

• On subsequent visits:

1. Cached version of all app files are used

• Fast load time!

• Potentially out of date!

2. Check if manifest file has changed

IAEA

Caching hell & double reloads

• Manifest is only checked on first load

• Long running apps won’t know there’s a new version

• Only the manifest file is checked

• Changes in other files will not be detected

• If there is a new version it will be silently downloaded

• User is not automatically informed

• Changes are not applied until reload

IAEA

Caching hell & double reloads

• Mitigation:

1. Auto-generate the manifest

• Put a content hash of cached files in a comment

CACHE*MANIFEST*!

CACHE:*#-app.js-hash:-1921ec2e922f7f11c73c870e908b1c50-/js/app.js

IAEA

Caching hell & double reloads

• Mitigation:

2. Notify the user

applicationCache.addEventListener('updateready',*function*()*{***//*let*the*user*know*that*they*need*to*reload*});

IAEA

Caching hell & double reloads

• During development you may spend a lot of time reloading the app

• 1 reload is not enough

• 1st reload will download the changes

• 2nd will put them into effect

• 2 reloads is tedious

• If you reload too quickly it might not work

IAEA

Caching hell & double reloads

• Mitigation:

3. Periodically check for a new version

setInterval(function*()*{***applicationCache.update();*},*config.newVersionCheckInterval);

• If the manifest has changed then it will be downloaded in the background

IAEA

Toggle online only features

• Some features require a server

• We can check network connection status

• Also need to check if the server can be reached

IAEA

Toggle online only features

• Detecting network availability

var*updateNetworkStatus*=*function*()*{***if*(applicationController.get('isNetworkConnected')*!==*navigator.onLine)*{*****applicationController.set('isNetworkConnected',*navigator.onLine);*****//*if*we*just*moved*from*offline*to*online*check*for*app*update*****if*(navigator.onLine)*{*******applicationCache.update();*****}***}*};*window.addEventListener('online',*updateNetworkStatus);*window.addEventListener('offline',*updateNetworkStatus);

IAEA

Toggle online only features

• Detecting service availability

var*updateServiceStatus*=*function*(status)*{***applicationController.set('isServiceAvailable',*status.type*!==*'error');*};*!

applicationCache.addEventListener('error',*updateServiceStatus);*applicationCache.addEventListener('noupdate',*updateServiceStatus);*applicationCache.addEventListener('updateready',*updateServiceStatus);

IAEA

Toggle online only features

• Putting network and service status together

isOnline:*function*()*{***return*this.get('isNetworkConnected')*&&*this.get('isServiceAvailable');*}.property('isNetworkConnected',*'isServiceAvailable')

IAEA

Data Access

• Ember data offers useful layered abstractions

• An adaptor lets you communicate with your data source

• A serialiser lets you transform from the format of your source to the format expected by ember

• The store provides an agnostic API for application to load and save models

IAEA

Data Access

• Server side we’re using ASP.NET MVC Web API

• Requires a custom Adaptor and Serialiser

• Adding offline support at the adaptor level is easy

• Application code does not need know

IAEA

Data Access

• Oversimplified data adaptor

var*CacheAdapter*=*DS.RESTAdapter.extend({***ajax:*function*(url,*type,*options)*{*****if*(App.get('isOnline'))*{*******options.success*=*function*(responseData)*{*********cacheResponse(url,*type,*options,*responseData);*******};*******return*this._super(url,*type,*options);*****}*else*{*******return*cachedResponse(url,*type,*options);*****}***}*});

IAEA

Data Access

• Not always desirable to cache every response

• Pass intentions to store methods

IAEA

Data Accessstore.findById('person',*id,*{*cacheResponse:*true*});

var*CacheStore*=*DS.Store.extend({***findById:*function*(type,*id,*options)*{*****return*this.findQuery(type,*{*id:*id*},*options).then(function*(result)*{*******return*result.get('firstObject');*****});***},*!

**findQuery:*function*(type,*data,*options)*{*****data*=*data*||*{};*****data.__options*=*options*||*{};*****return*this._super(type,*data);***}*});

IAEA

Hold on… “new” requirement

• We forgot to mention…

• Sometimes it’s not possible to bring the laptop/tablet back to headquarters

• How can you deploy and update a web app to a computer that never connects to the server?

IAEA

Hold on… “new” requirement

• At a small number of locations, the only hardware allowed back to HQ is a hardware encrypted USB stick…

• Put the browser on the USB stick

• Configure the browser to store all data cache data on the USB

• Now when at HQ the browser will update the app and store data needed ready for offline use

IAEA

Recap

• Ember offers the structure necessary for large (and small) projects

• Build tools like ember-cli give you manageable output for manifest.appcache and can easily be extended to automate its content

• Build automation is essential from the start when using appcache

• Ember data has the abstractions necessary to provide good offline support which can be transparent to your app

• There’s not much that you can’t do with Ember.js “web” application

IAEA

Questions?