Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Progressive Angular apps

Ciro Nunes
November 22, 2016

Progressive Angular apps

20 minutes talk about Progressive Web Apps with Angular 2

Ciro Nunes

November 22, 2016
Tweet

More Decks by Ciro Nunes

Other Decks in Technology

Transcript

  1. { "name": "Ali Express", "short_name": "AliExpress", "icons": [{ "src": "images/icons/icon-128x128.png",

    "sizes": "128x128", "type": "image/png" }], "start_url": "/index.html", "display": "standalone", "background_color": "#3E4EB8", "theme_color": "#2F3BA2" } manifest.webapp
  2. var cacheName = 'myApp'; var filesToCache = [...]; self.addEventListener('install', function(e)

    { e.waitUntil( caches.open(cacheName).then(function(cache) { return cache.addAll(filesToCache); }) ); }); service-worker.js ADD TO CACHE
  3. self.addEventListener('activate', (e) => { e.waitUntil(self.clients.claim()); e.waitUntil( caches.keys().then((keyList) => { return

    Promise.all(keyList.map((key) => { if (key !== cacheName) { return caches.delete(key); } })); }) ); }); service-worker.js CLEAR CACHE
  4. self.addEventListener('fetch', function(e) { var dataUrl = 'https://sample-api.com'; if (e.request.url.indexOf(dataUrl) >

    -1) { e.respondWith( caches.open(dataCacheName).then(function(cache) { return fetch(e.request).then(function(response){ cache.put(e.request.url, response.clone()); return response; }); }) ); } else { e.respondWith( caches.match(e.request).then(function(response) { return response || fetch(e.request); }) ); } }); service-worker.js
  5. self.addEventListener('fetch', function(e) { var dataUrl = 'https://sample-api.com'; if (e.request.url.indexOf(dataUrl) >

    -1) { e.respondWith( caches.open(dataCacheName).then(function(cache) { return fetch(e.request).then(function(response){ cache.put(e.request.url, response.clone()); return response; }); }) ); } else { e.respondWith( caches.match(e.request).then(function(response) { return response || fetch(e.request); }) ); } }); service-worker.js
  6. self.addEventListener('fetch', function(e) { var dataUrl = 'https://sample-api.com'; if (e.request.url.indexOf(dataUrl) >

    -1) { e.respondWith( caches.open(dataCacheName).then(function(cache) { return fetch(e.request).then(function(response){ cache.put(e.request.url, response.clone()); return response; }); }) ); } else { e.respondWith( caches.match(e.request).then(function(response) { return response || fetch(e.request); }) ); } }); service-worker.js
  7. self.addEventListener('fetch', function(e) { var dataUrl = 'https://sample-api.com'; if (e.request.url.indexOf(dataUrl) >

    -1) { e.respondWith( caches.open(dataCacheName).then(function(cache) { return fetch(e.request).then(function(response){ cache.put(e.request.url, response.clone()); return response; }); }) ); } else { e.respondWith( caches.match(e.request).then(function(response) { return response || fetch(e.request); }) ); } }); service-worker.js
  8. caches.match(e.request.clone()).then((response) => { return response || fetch(e.request.clone()).then((theResponse) => { return

    caches.open(dataCacheName).then((cache) => { cache.put(e.request.url, theResponse.clone()); return theResponse.clone(); }); }); }); service-worker.js
  9. ~ $ npm i --save @angular/app-shell // App code import

    { AppShellModule } from '@angular/app-shell'; @NgModule({ bootstrap: [AppComponent], imports: [ BrowserModule, AppShellModule.runtime(), AppModule })
  10. @Component({ selector: 'app-root-component', template: ` <!-- Only show loading indicator

    in the shell --> <loading-indicator *shellRender> </loading-indicator> <!-- Hide a dynamic view until runtime --> <dynamic-view *shellNoRender> </dynamic-view> ` }) export class AppRootComponent {}
  11. ~ $ npm i --save @angular/service-worker // worker-basic.min.js is copied

    from // node_modules/@angular/service-worker/bundles if (navigator.serviceWorker) { navigator.serviceWorker.register('/worker-basic.min.js'); }
  12. { "routing": { "routes": { "/": { "prefix": false }

    }, "index": "/index.html" } } ngsw-manifest.json
  13. self.addEventListener('push', function(e) { e.waitUntil( fetch('http://localhost:8090/pushdata').then(function(response) { return response.json(); }).then(function(data) {

    return self.registration.showNotification(title, { body: body, icon: icon, tag: tag }); }, function(err) { err(err); }) ); }); worker-push.js
  14. self.addEventListener('push', function(e) { e.waitUntil( fetch('http://localhost:8090/pushdata').then(function(response) { return response.json(); }).then(function(data) {

    return self.registration.showNotification(title, { body: body, icon: icon, tag: tag }); }, function(err) { err(err); }) ); }); worker-push.js