Förderjahr 2018 / Project Call #13 / ProjektID: 3361 / Projekt: Hedgehog Cloud
Immer mehr Aspekte unseres Lebens sind nicht nur digital, sondern auch in der einen oder anderen Weise in der Cloud. Statt Thunderbird und Outlook lesen wir Emails in einem Webmail Client. Statt Libre- oder Microsoft Office bearbeiten wir Dokumente in Google Drive. Vom klassischen Social Media ganz zu schweigen.
Dass Nachrichten und Social Media ohne Internetzugang nicht funktionieren, sollte klar sein - ob über Browser oder App, wo sollen die neuen Inhalte denn herkommen? Aber gerade bei Office-Anwendungen sieht die Sache doch theoretisch anders aus: wenn ich ein Dokument erstelle, brauche ich keine aktuellen Daten von außen; notwendig ist nur die Anwendung, mit der ich mein Dokument bearbeite. Bei dieser Art von Anwendung an die Offline-Fähigkeit zu denken ist sinnvoll, ein Online-Zwang wäre für die Benutzer sehr einschränkend.
Für manche mag es vielleicht überraschend klingen, aber auch Web-Anwendungen können offline-fähig sein. Die Technologie, die das ermöglicht sind sogenannte "Service Workers".
Service Workers
Im Web-Sprech ist ein "Worker" ein Hintergrundthread, der einer Website zugeordnet ist und der eingentlichen Seite Arbeiten abnimmt. Das können zum Beispiel Berechnungen sein, die ansonsten den Browser lahmlegen würden - die Möglichkeiten sind vielseitig. Service Workers sind eine spezielle Variante, die sich zwischen Server und Browser stellen, und die Beantwortung von Requests übernehmen können. Statt dem Server kann dann der Service Worker die Anfragen direkt beantworten, sofern er die Antwort kennt. Service Worker können auch aktiv bleiben, wenn die Website in keinem Tab geöffnet ist, zum Beispiel um Daten im Hintergrund zu aktualisieren.
Für den Fall dass es noch nicht deutlich geworden ist: sobald ein Service Worker aktiv ist, hat er extreme Macht über die kontrollierte Website. Er kann alle Anfragen an den Server lesen und beliebig beantworten. Entsprechend streng sind die Bedingungen unter denen ein Service Worker für eine Website installiert werden kann.
Offline-Fähigkeit mit Workbox
Die Möglichkeiten eines Service Workers sind eindeutig spannend für Offline-Fähigkeit. Unter den vielfältigen Möglichkeiten ist die, eine komplett offlinefähige Webanwendung zu erstellen: beim Registrieren "installiert" der Service Worker die Anwendung in einem Cache des Browsers, danach kann er die Anwendung auch ohne Internetverbindung ausliefern. Sogar zwischenspeichern von Daten, die mit der Cloud synchronisiert werden müssen, ist denkbar. Um Aufgaben dieser Art komfortabler zu gestalten, gibt es von Google Workbox, und so einfach kann es sein, damit seine App offlinefähig zu machen:
Webpack-Plugin
Die Hedgehog-Ide benutzt Webpack, da bietet sich das `workbox-webpack-plugin` an. Nachdem das Plugin installiert ist, fügen wir es in die Webpack-Konfiguration ein:
import WorkboxPlugin from 'workbox-webpack-plugin';
const config = {
// ...
plugins: [
// ...
new WorkboxPlugin.InjectManifest({
importWorkboxFrom: 'local',
swSrc: 'src/serviceworker/index.js',
swDest: 'sw.js',
}),
],
};
export default config;
Das Webpack-Plugin erkennt, welche Ressourcen bei unserem Build-Prozess entstehen und schreibt diese in eine "precache manifest" Datei, die dann im Browser von Workbox gelesen wird. Wir benutzen das `InjectManifest` plugin, das heißt das Plugin erweitert unser `src/serviceworker/index.js` um das Laden von Workbox und dieser JSON-Datei. Für einfache Fälle reicht das `GenerateSW` plugin, wo der gesamte Service Worker code generiert wird. Außerdem gewöhnen wir Workbox noch ab, den eigenen Code von einem Google CDN zu laden, wir haben es da lieber, allen Code selbst zu hosten.
Der Service Worker
Der Code, den das Webpack-Plugin ausspuckt, sieht am Ende so (natürlich ohne den deutschsprachigen Kommentaren) aus:
// von Webpack generiert
importScripts("/assets/precache-manifest.e1e95736cd34853583a4ae7380ef59fc.js", "/assets/workbox-v4.3.1/workbox-sw.js");
workbox.setConfig({modulePathPrefix: "/assets/workbox-v4.3.1"});
// unser Code in src/serviceworker/index.js
workbox.core.skipWaiting();
workbox.core.clientsClaim();
/**
* The workboxSW.precacheAndRoute() method efficiently caches and responds to
* requests for URLs in the manifest.
* See https://goo.gl/S9QRab
*/
self.__precacheManifest = [].concat(
[{ url: '/' }],
self.__precacheManifest || [],
);
workbox.precaching.precacheAndRoute(self.__precacheManifest, {});
Abgesehen von den Ressourcen in Precache-Manifest fügen wir noch die Route { url: '/' } hinzu, damit auch die Homepage offline verfügbar ist.
Registrierung
Bleibt nur noch, den Service Worker zu registrieren, das ist nicht spezifisch zu Workbox:
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js', { scope: '/' });
});
}
Fazit
Tada! So einfach kann es sein, kaum zu glauben. Ok, es könnte sein, dass wir hier noch einige Feinheiten ausgelassen haben:
- aktuell muss man zuerst die Homepage aufrufen (Route `/`), erst dann funktioniert etwa die Seite `/projects`, weil diese nicht im Service Worker registriert ist. Dafür hilft etwa, die Links als `/#/projects` zu gestalten.
- iframes mit Sandbox laden ihre Ressourcen nicht durch den Service Worker - das heißt aktuell geht zwar Code schreiben, nicht aber ausführen, offline. Aber auch dafür gibt es Lösungen: Ressourcen außerhalb des iframes Laden, und dem iframe dann zur Verfügung stellen.
Da ist also noch Arbeit vor uns, aber sie geht mit großen Schritten voran!