Taking Your “Web” App 
To places you never expected 
Garth Williams 
@williamsgarth 
IAEA 
International Atomic Energy Agency
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 Access 
store.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?

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

  • 1.
    Taking Your “Web”App To places you never expected Garth Williams @williamsgarth IAEA International Atomic Energy Agency
  • 2.
    IAEA Introduction IAEAHeadquarters in Vienna http://iaea.org
  • 3.
    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
  • 4.
    IAEA Let’s useWPF? • 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)
  • 5.
    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
  • 6.
    IAEA Ember isa 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
  • 7.
    IAEA Taking emberoffline (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>
  • 8.
    IAEA Taking emberoffline (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
  • 9.
    IAEA What aboutmy 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
  • 10.
    IAEA What aboutmy beautiful client side URLs? • But now I’m using push state, how can this dynamic url be available offline? • https://stunningapp.com/entity/5/
  • 11.
    IAEA What aboutmy 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
  • 12.
    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
  • 13.
    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
  • 14.
    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
  • 15.
    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
  • 16.
    IAEA Caching hell & double reloads • Mitigation: 2. Notify the user applicationCache.addEventListener('updateready',*function*()*{* **//*let*the*user*know*that*they*need*to*reload* });
  • 17.
    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
  • 18.
    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
  • 19.
    IAEA Toggle onlineonly features • Some features require a server • We can check network connection status • Also need to check if the server can be reached
  • 20.
    IAEA Toggle onlineonly 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);
  • 21.
    IAEA Toggle onlineonly 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);
  • 22.
    IAEA Toggle onlineonly features • Putting network and service status together isOnline:*function*()*{* **return*this.get('isNetworkConnected')*&&*this.get('isServiceAvailable');* }.property('isNetworkConnected',*'isServiceAvailable')
  • 23.
    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
  • 24.
    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
  • 25.
    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);* ****}* **}* });
  • 26.
    IAEA Data Access • Not always desirable to cache every response • Pass intentions to store methods
  • 27.
    IAEA Data Access store.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);* **}* });
  • 28.
    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?
  • 29.
    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
  • 30.
    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
  • 31.