Offline webapps reimagined

Szmozsánszky István




Carnation / POSSIBLE Budapest
Frontend Developer


Mozilla
Firefox OS Developer Engagement

YE OLDEN DAYS

with appcache being a douchebag

...AND THEN, THE SERVICE WORKER COMETH

Modern web apis 101

function myAsyncFunction(input, callback) {
    var myThing = doMyThing(input);

    doMyThing.oncomplete = callback;
}

function nextAsyncFunction(secondInput, callback) {
    var myOtherThing =
        doMyOtherThing(secondInput);

    myOtherThing.onComplete = callback;
}

myAsyncFunction(1, function(result) {
    nextAsyncFunction(result,
        function(secondresult) {
            console.log(secondresult);
        }
    );
});
function myAsyncFunction(input) {
    var myThing = doMyThing(input);

    return doMyThing.promise;
}

function nextAsyncFunction(secondInput) {
    var myOtherThing =
        doMyOtherThing(secondInput);

    return myOtherThing.promise;
}

myAsyncFunction(1)
    .then(nextAsyncFunction)
    .then(function(secondresult) {
        console.log(secondresult);
    });

WhatWG Fetch API polyfill on GitHub & NPM


var r = new XMLHttpRequest();

r.open("POST", "/api/users", true);

r.onreadystatechange = function () {
    if (r.readyState != 4) return;

    if (r.status != 200) {
        console.log("Request failed!");
    }

    console.log("Success: " + r.responseText);
};

r.setRequestHeader("Content-Type", "application/json");

r.send('{"name: "Flaki", "login": "slsoftworks" }');

fetch('/api/users', {

  method: 'post',

  headers: {
    'Content-Type': 'application/json'
  },

  body: JSON.stringify({
    name: 'Flaki',
    login: 'slsoftworks',
  })

}).then(function(result) {
    console.log("Success: " + result);

}).catch(function(error) {
    console.log("Request failed!");

});

Service workers

the hands-on experience

USAGE

  • Installing / updating service workers
  • Caching assets
  • Fetching and serving resources
  • Support (Chrome, Firefox - desktop & mobile)

Registering

// Note: ONLY HTTPS!
navigator.serviceWorker.register('/serviceworker.js', {

  // Service Worker events are scoped
  // to this subfolder only
  scope: '/trained-to-thrill/'

}).then(function(reg) {
  console.log('Service Worker on line!');

}, function(err) {
  console.log('Oops, Service Worker installation failed!');

});

the  Serviceworker.js

// The SW will be shutdown when not in use to save memory,
// be aware that any global state is likely to disappear

console.log("SW startup");

self.addEventListener('install', function(event) {
  console.log("SW installed");
});

self.addEventListener('activate', function(event) {
  console.log("SW activated");
});

self.addEventListener('fetch', function(event) {
  console.log("Caught a fetch!");
  event.respondWith(new Response("Hello world!"));
});

UPDATING & REPLACING

 

 

// Installation
self.addEventListener('install', function(event) {
  console.log("Installing…");

  event.waitUntil(
    somethingThatReturnsAPromise().then(function() {
      console.log("Installed!");
    })
  );
});

// Activation
self.addEventListener('activate', function(event) {
  console.log("Activating…");

  event.waitUntil(
    somethingThatReturnsAPromise().then(function() {
      console.log("Activated!");
    })
  );
});

Cached responses

 

importScripts('serviceworker-cache-polyfill.js');

self.addEventListener('install', function(event) {
  // pre cache a load of stuff:
  event.waitUntil(
    cachesPolyfill.open('myapp-static-v1').then(function(cache) {
      return cache.addAll([
        '/',
        '/styles/all.css',
        '/styles/imgs/bg.png',
        '/scripts/all.js'
      ]);
    })
  )
});

self.addEventListener('fetch', function(event) {
  event.respondWith(
    cachesPolyfill.match(event.request).then(function(response) {
      return response || fetch(event.request);
    })
  );
});

NOT JUST OFFLINE

Every byte not transferred
is a byte saved!

the future

geofencing, background sync and push

thank you!

questions?

http://slid.es/flaki/offline

@slsoftworks
2014. 11. 12.

Made with Slides.com