Text
PWAs are the missing technology link to bring the best features of the web to solve the issues of native apps and closed marketplaces.
Chris Heilmann
Alibaba
(e-commerce/China)
Source : https://developers.google.com/web/showcase/2016/pdfs/alibaba.pdf
FlipKart
(e-commerce/India)
https://developers.google.com/web/showcase/2016/flipkart
Connectivity-independant
Linkable
Installable
Re-engageable
Discoverable
Fresh
App-Like
if("geolocation" in navigator) {
  navigator.geolocation.getCurrentPosition(pos => {
  });
} else {
}
 
<meta property="og:title" content="titre"/>
<meta property="og:type" content="website"/>Les fonctionnalités, que nous allons vous présenter, font parties juste d'un toolkit.
npm i -g lighthouse
lighthouse https://google.fr<!doctype html>
<html lang="fr">
    <head>
        <meta http-equiv="Content-Type" 
            content="text/html; charset=utf-8" />
	
        <meta content="width=device-width, initial-scale=1.0" 
            name="viewport" />
        
        <title>Ma première PWA</title>
        <link rel="manifest" href="manifest.json">
    </head>
    <body>
    
    </body>
</html>Style
Display
https://manifest-validator.appspot.com
window.addEventListener(
    'beforeinstallprompt', (e) => { 
      if (isLoggedIn()) {
        e.preventDefault();
      } 
    });const fs = require('fs')
const javascript = fs.readFileSync('./app/assets/script.js');
app.get('/', (req, res) => {
    res.push('/script.js', { 
        response: {'content-type': 'application/javascript'}})
            .end(javascript)
    
    res.sendFile(__dirname + '/app/index.html');
})
const options = {
    key: fs.readFileSync('./server.key'),
    cert: fs.readFileSync('./server.crt')
};
require('spdy').createServer(options, app).listen(3002);Service Worker
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('./sw.js')
    .then(req => {
        console.log('Success');
      }).catch(error => {
        console.log('Error');
      });
};self.addEventListener('fetch', event => {
  event.respondWith(
        fetch(event.request)
  );
});self.addEventListener('fetch', event => {
  event.respondWith(
        fetch(event.request)
            .then(response => {
                if(response.status === 404) {
                    ...
                }
                return response;
            })
  );
});interface Request {
    method
    url
    headers
    context
    referrer
    referrerPolicy
    mode
    credentials
    redirect
    integrity
    cache
    bodyUsed
}self.addEventListener('fetch', event => {
  
  /*
  let options = {
    status: 200, 
    statustext: 'OK',
    headers: { ... }
  };
  */
  event.respondWith(
       new Response('Hello World', /*opts*/)        
  );
});CacheStorage.open(cacheName)
Cache.match(request, options)
Cache.matchAll(request, options)
Cache.add(request)
Cache.addAll(requests)
Cache.put(request, response)
Cache.delete(request, options)const cacheName = 'codelab';
const filesToCache = [
  '/',
  '/script.js',
  '/css/style.css'
];
self.addEventListener('install', e => {
  e.waitUntil(
    caches.open(cacheName).then(cache => {
      return cache.addAll(filesToCache);
    })
  );
});self.addEventListener('fetch', e => {
  e.respondWith(
      caches.match(e.request)
        .then(response => {
            return response || fetch(e.request);
        })
  );
});self.addEventListener('activate', e => {
  e.waitUntil(
    caches.keys().then(keyList => {
      return Promise.all(keyList.map(key => {
        if (key !== cacheName) {
          return caches.delete(key);
        }
      }));
    })
  );
});if(!navigator.onLine) {
    ...
}
window.addEventListener("offline", () => {
    ...
}, false);
window.addEventListener("online", () => {
    ...
}, false);const indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB;
// Open (or create) the database
const open = indexedDB.open("Codelab", 1);
// Create the schema
open.onupgradeneeded = function() {
    let db = open.result;
    let store = db.createObjectStore("Conference", {keyPath: "id"});
    let index = store.createIndex("SpeakerIndex", ["speaker"]);
};
open.onsuccess = function() {
    // Start a new transaction
    let db = open.result;
    let tx = db.transaction("Conference", "readwrite");
    let store = tx.objectStore("Conference");
    let index = store.index("SpeakerIndex");
    // Add some data
    store.put({id: 12345, speaker: "Manu", "title": "PWA");
    store.put({id: 67890, speaker: "Gauthier", "title": "VueJS");
    
    // Query the data
    let getPWA = store.get(12345);
    let getVueJS = index.get(["Gauthier"]);
    getPWA.onsuccess = function() {
        console.log(getPWA.result);
    };
    getVueJS.onsuccess = function() {
        console.log(getBob.result);
    };
    // Close the db when the transaction is done
    tx.oncomplete = function() {
        db.close();
    };
}localforage.setItem('somekey', {}).then(value => {
    console.log(value);
})
localforage.getItem('somekey').then(value => {
    console.log(value);
});
localforage.removeItem('somekey').then(() => {
    console.log('Key is cleared!');
});self.addEventListener('sync', event => {
  if (event.tag == 'SYNC_SETTINGS') {
    event.waitUntil(updateSettings());
  }
});navigator.serviceWorker.getRegistration()
    .then(registration => {
        registration.sync.register(
            'SYNC_SETTINGS').then(() => {
                console.log('Sync registered');
            });
    })