Mainline ist ein Online-Bekleidungshändler, der die größten Designermarken der Mode anbietet. Das im Vereinigten Königreich ansässige Unternehmen vertraut auf ein Team aus internen Experten, das strategisch mit wichtigen Partnern zusammenarbeitet, um allen ein reibungsloses Einkaufserlebnis zu bieten. Mit einer Marktpräsenz in über 100 Ländern über sieben individuell erstellte länderspezifische Websites und eine App wird Mainline weiterhin dafür sorgen, dass das E-Commerce-Angebot mit der Konkurrenz mithalten kann.
Herausforderung
Das Ziel von Mainline Menswear bestand darin, die aktuelle für Mobilgeräte optimierte Website um progressive Funktionen zu ergänzen, die dem Konzept „Mobile first“ entsprechen. Dabei wurde ein besonderer Fokus auf ein für Mobilgeräte optimiertes Design und Funktionen gelegt, die auf den wachsenden Smartphone-Markt ausgerichtet sind.
Lösung
Ziel war es, eine PWA zu entwickeln und zu veröffentlichen, die die ursprüngliche mobilfreundliche Version der Mainline Menswear-Website ergänzt. Anschließend sollten die Statistiken mit denen der hybriden mobilen App verglichen werden, die derzeit für Android und iOS verfügbar ist.
Nachdem die App veröffentlicht und von einem kleinen Teil der Mainline Menswear-Nutzer verwendet wurde, konnte das Team die Unterschiede bei den wichtigsten Statistiken zwischen PWA, App und Web ermitteln.
Bei der Umwandlung der Website in eine PWA verfolgte Mainline bei der Umwandlung der Website in eine PWA, dass das für die Website ausgewählte Framework (Nuxt.js, verwendet Vue.js) zukunftssicher ist und die Vorteile der sich schnell entwickelnden Webtechnologie nutzen kann.
Ergebnisse
139 %
Mehr Seiten pro Sitzung in der PWA als im Web.
161 %
Längere Sitzungsdauer in PWAs im Vergleich zum Web
10 %
niedrigere Absprungrate in PWA im Vergleich zu Web
12,5 %
höherer durchschnittlicher Bestellwert in PWAs als im Web
55 %
Höhere Conversion-Rate in der PWA als im Web.
243%
Höherer Umsatz pro Sitzung in PWA als im Web.
Technische Details
Mainline Menswear verwendet das Nuxt.js-Framework, um seine Website zu bündeln und zu rendern. Dabei handelt es sich um eine Single-Page-Anwendung (SPA).
Service Worker-Datei generieren
Zum Generieren des Service Workers fügte Mainline Menswear über eine benutzerdefinierte Implementierung des nuxt/pwa
Workbox-Moduls eine Konfiguration hinzu.
Das Team hat das nuxt/pwa
-Modul geforkt, damit es der Service Worker-Datei weitere Anpassungen hinzufügen konnte, die bei der Verwendung der Standardversion nicht möglich waren oder bei denen es Probleme gab.
Eine dieser Optimierungen betraf die Offlinefunktionen der Website, z. B. die Bereitstellung einer Standard-Offlineseite und die Erhebung von Analysedaten im Offlinemodus.
Aufbau des Web-App-Manifests
Das Team generierte ein Manifest mit Symbolen für verschiedene Größen von Symbolen für mobile Apps und anderen Details für Webanwendungen wie name
, description
und theme_color
:
{
"name": "Mainline Menswear",
"short_name": "MMW",
"description": "Shop mens designer clothes with Mainline Menswear. Famous brands including Hugo Boss, Adidas, and Emporio Armani.",
"icons": [
{
"src": "/_nuxt/icons/icon_512.c2336e.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#107cbb"
}
Nach der Installation kann die Web-App vom Startbildschirm aus gestartet werden, ohne dass der Browser gestört wird. Dazu fügen Sie den Parameter display
in die Manifestdatei der Webanwendung ein:
{
"display": "standalone"
}
Und zu guter Letzt kann das Unternehmen jetzt ganz einfach nachverfolgen, wie viele Nutzer seine Webanwendung über den Startbildschirm aufrufen. Dazu fügt es einfach einen utm_source
-Parameter in das Feld start_url
des Manifests ein:
{
"start_url": "/?utm_source=pwa"
}
Laufzeit-Caching für schnellere Navigation
Caching für Webanwendungen ist ein Muss, um die Seitengeschwindigkeit zu optimieren und wiederkehrenden Nutzern eine bessere Nutzererfahrung zu bieten.
Für das Caching im Web gibt es einige verschiedene Ansätze. Das Team verwendet eine Mischung aus dem HTTP-Cache und der Cache API, um Assets clientseitig zu cachen.
Mit der Cache API hat Mainline Menswear eine genauere Kontrolle über die im Cache gespeicherten Assets und kann für jeden Dateityp komplexe Strategien anwenden. Das klingt zwar kompliziert und schwierig einzurichten und zu verwalten, aber Workbox bietet eine einfache Möglichkeit, solche komplexen Strategien zu deklarieren und die Wartung zu erleichtern.
CSS und JS im Cache speichern
Für CSS- und JS-Dateien entschied sich das Team, sie im Cache zu speichern und über den Cache mit der Workbox-Strategie StaleWhileRevalidate
bereitzustellen. Mit dieser Strategie können alle Nuxt-CSS- und JS-Dateien schnell bereitgestellt werden, was die Leistung der Website erheblich steigert.
Gleichzeitig werden die Dateien im Hintergrund auf die neueste Version für den nächsten Besuch aktualisiert:
/* sw.js */
workbox.routing.registerRoute(
/\/_nuxt\/.*(?:js|css)$/,
new workbox.strategies.StaleWhileRevalidate({
cacheName: 'css_js',
}),
'GET',
);
Google-Schriftarten im Cache speichern
Die Strategie zum Caching von Google Fonts hängt von zwei Dateitypen ab:
- Das Stylesheet, das die
@font-face
-Deklarationen enthält - Die zugrunde liegenden Schriftdateien (im oben genannten Stylesheet angefordert).
// Cache the Google Fonts stylesheets with a stale-while-revalidate strategy.
workbox.routing.registerRoute(
/https:\/\/fonts\.googleapis\.com\/*/,
new workbox.strategies.StaleWhileRevalidate({
cacheName: 'google_fonts_stylesheets',
}),
'GET',
);
// Cache the underlying font files with a cache-first strategy for 1 year.
workbox.routing.registerRoute(
/https:\/\/fonts\.gstatic\.com\/*/,
new workbox.strategies.CacheFirst({
cacheName: 'google_fonts_webfonts',
plugins: [
new workbox.cacheableResponse.CacheableResponsePlugin({
statuses: [0, 200],
}),
new workbox.expiration.ExpirationPlugin({
maxAgeSeconds: 60 * 60 * 24 * 365, // 1 year
maxEntries: 30,
}),
],
}),
'GET',
);
Bilder im Cache speichern
Für Bilder hat sich Mainline Menswear für zwei Strategien entschieden. Die erste Strategie gilt für alle Bilder, die über das CDN bereitgestellt werden, in der Regel Produktbilder. Die Seiten sind bildlastig, daher ist es wichtig, dass nicht zu viel Speicherplatz auf den Geräten der Nutzer belegt wird. Deshalb hat das Team mit Workbox eine Strategie hinzugefügt, mit der nur Bilder aus dem CDN im Cache gespeichert werden. Dabei wird mit der ExpirationPlugin
ein Maximum von 60 Bildern festgelegt.
Das 61. (neueste) angeforderte Bild ersetzt das 1. (älteste) Bild, sodass zu keinem Zeitpunkt mehr als 60 Produktbilder im Cache gespeichert sind.
workbox.routing.registerRoute(
({ url, request }) =>
url.origin === 'https://mainline-menswear-res.cloudinary.com' &&
request.destination === 'image',
new workbox.strategies.StaleWhileRevalidate({
cacheName: 'product_images',
plugins: [
new workbox.expiration.ExpirationPlugin({
// Only cache 60 images.
maxEntries: 60,
purgeOnQuotaError: true,
}),
],
}),
);
Die zweite Bildstrategie verarbeitet die restlichen vom Ursprung angeforderten Bilder. Diese Bilder sind in der Regel sehr wenige und klein. Zur Sicherheit ist die Anzahl dieser im Cache gespeicherten Bilder jedoch auf 60 Bilder begrenzt.
workbox.routing.registerRoute(
/\.(?:png|gif|jpg|jpeg|svg|webp)$/,
new workbox.strategies.StaleWhileRevalidate({
cacheName: 'images',
plugins: [
new workbox.expiration.ExpirationPlugin({
// Only cache 60 images.
maxEntries: 60,
purgeOnQuotaError: true,
}),
],
}),
);
Offlinefunktionen bereitstellen
Die Offline-Seite wird direkt nach der Installation und Aktivierung des Service Workers vorab im Cache gespeichert. Dazu erstellen sie eine Liste aller Offlineabhängigkeiten: die Offline-HTML-Datei und ein Offline-SVG-Symbol.
const OFFLINE_HTML = '/offline/offline.html';
const PRECACHE = [
{ url: OFFLINE_HTML, revision: '70f044fda3e9647a98f084763ae2c32a' },
{ url: '/offline/offline.svg', revision: 'efe016c546d7ba9f20aefc0afa9fc74a' },
];
Die Liste für die Vorab-Caching-Dateien wird dann an Workbox übergeben, die die URLs in den Cache einfügt, nach Übereinstimmungen der Versionen sucht, die Dateien aktualisiert und sie mit einer CacheFirst
-Strategie ausliefert.
workbox.precaching.precacheAndRoute(PRECACHE);
Offlinenavigationen verarbeiten
Sobald der Dienst-Worker aktiviert und die Offlineseite vorab im Cache gespeichert ist, wird sie verwendet, um auf Offlinenavigationsanfragen des Nutzers zu antworten. Die Webanwendung von Mainline Menswear ist eine SPA. Die Offlineseite wird jedoch erst angezeigt, wenn die Seite neu geladen wird, der Nutzer den Browsertab schließt und wieder öffnet oder die Webanwendung im Offlinemodus über den Startbildschirm gestartet wird.
Dazu hat Mainline Menswear einen Fallback für fehlgeschlagene NavigationRoute
-Anfragen mit der vorab im Cache gespeicherten Offlineseite bereitgestellt:
const htmlHandler = new workbox.strategies.NetworkOnly();
const navigationRoute = new workbox.routing.NavigationRoute(({ event }) => {
const request = event.request;
// A NavigationRoute matches navigation requests in the browser, i.e. requests for HTML
return htmlHandler.handle({ event, request }).catch(() => caches.match(OFFLINE_HTML, {
ignoreSearch: true
}));
});
workbox.routing.registerRoute(navigationRoute);
Demo
Berichte über erfolgreiche Installationen
Neben dem Startbildschirm-Start-Tracking (mit "start_url": "/?utm_source=pwa"
im Manifest der Webanwendung) meldet die Webanwendung auch erfolgreiche App-Installationen, indem das Ereignis appinstalled
auf window
überwacht wird:
window.addEventListener('appinstalled', (evt) => {
ga('send', 'event', 'Install', 'Success');
});
Wenn du deiner Website PWA-Funktionen hinzufügst, können deine Kunden noch besser bei dir einkaufen. Außerdem lassen sich diese Apps schneller auf den Markt bringen als eine [plattformspezifische] App.
Andy Hoyle, Head of Development
Fazit
Weitere Informationen zu progressiven Web-Apps und deren Erstellung finden Sie im Abschnitt zu progressiven Web-Apps auf web.dev.
Weitere Fallstudien zu progressiven Web-Apps finden Sie im Abschnitt „Fallstudien“.