PWA mit Vue und Vite: offline und installierbar bauen
AI generated
<v/>
{ }
Vue.js · PWA · Vite · Offline First
PWA mit Vue und Vite: offline und installierbar
Service Worker, Manifest und Caching ohne App-Store-Umweg

Eine PWA mit Vue und Vite verwandelt eine bestehende Webanwendung in eine installierbare, offline-fähige App, ohne App-Store-Review und ohne separate native Codebasis. Mit vite-plugin-pwa lassen sich Service Worker, Web-App-Manifest und Caching-Strategien weitgehend automatisiert konfigurieren, während Update-Handling und Offline-Verhalten gezielt auf die eigene Anwendung zugeschnitten werden.

18 Min. Lesezeit Vue 3 · Vite · vite-plugin-pwa · Workbox Service Worker · Manifest · Caching

1. Was eine PWA von einer normalen Vue-Anwendung unterscheidet

Eine PWA mit Vue unterscheidet sich von einer normalen Webanwendung durch drei technische Zusätze: einen Service Worker, der Netzwerk-Requests abfangen und cachen kann, ein Web-App-Manifest, das dem Betriebssystem Metadaten für die Installation liefert, und eine HTTPS-Verbindung, die für Service Worker zwingend vorausgesetzt wird. Zusammen ermöglichen diese drei Bausteine, dass eine Vue-Anwendung auf dem Homescreen installiert werden kann und auch ohne Netzwerkverbindung zumindest teilweise funktioniert.

Der entscheidende Unterschied zu einer klassischen Webanwendung liegt im Service Worker als eigenständigem, vom Hauptthread getrennten JavaScript-Kontext, der zwischen Netzwerk und Anwendung sitzt. Jede Anfrage der Vue-PWA kann vom Service Worker abgefangen werden, bevor sie überhaupt das Netzwerk erreicht, was gezielte Caching-Entscheidungen ermöglicht: Statische Assets aus dem Cache liefern, API-Antworten mit Fallback auf gecachte Daten versehen, oder komplett offline aus dem Cache antworten.

Für Vue-Entwickler ist der pragmatische Einstieg in eine PWA mit Vue heute deutlich einfacher als noch vor einigen Jahren, weil vite-plugin-pwa die Erstellung von Manifest und Service Worker automatisiert und auf der bewährten Workbox-Bibliothek von Google aufbaut. Statt einen Service Worker von Grund auf selbst zu schreiben, konfiguriert man Caching-Strategien deklarativ in der Vite-Konfiguration, und das Plugin generiert daraus den passenden Service-Worker-Code bei jedem Build.

2. Projekt-Setup mit vite-plugin-pwa

Der Einstieg in eine PWA mit Vue beginnt mit der Installation von vite-plugin-pwa in ein bestehendes Vue-3-Projekt mit Vite als Build-Tool. Das Plugin wird in der vite.config.js registriert und übernimmt ab diesem Zeitpunkt automatisch die Generierung von Manifest-Datei und Service Worker bei jedem Produktions-Build, ohne dass diese Dateien manuell gepflegt werden müssen.

Für die Entwicklung ist besonders die Option devOptions.enabled relevant, die den Service Worker auch im lokalen Vite-Dev-Server aktiviert. Ohne diese Option lässt sich Offline-Verhalten während der Entwicklung nur schwer testen, weil Service Worker standardmäßig nur in Produktions-Builds registriert werden.


# Add the PWA plugin to an existing Vue 3 + Vite project
npm install -D vite-plugin-pwa

// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { VitePWA } from 'vite-plugin-pwa'

export default defineConfig({
  plugins: [
    vue(),
    VitePWA({
      registerType: 'prompt',      // let the user decide when to activate updates
      devOptions: {
        enabled: true,             // test the service worker during `vite dev`
      },
      manifest: {
        name: 'Mironsoft App',
        short_name: 'Mironsoft',
        theme_color: '#16a34a',
        background_color: '#0f172a',
        display: 'standalone',
        icons: [
          { src: 'icon-192.png', sizes: '192x192', type: 'image/png' },
          { src: 'icon-512.png', sizes: '512x512', type: 'image/png' },
        ],
      },
      workbox: {
        globPatterns: ['**/*.{js,css,html,svg,png,webp}'],
      },
    }),
  ],
})

Nach dem Build erzeugt vite-plugin-pwa automatisch eine manifest.webmanifest-Datei sowie einen Service-Worker-Bundle im dist-Verzeichnis, beide bereits mit den korrekten Verweisen im HTML-Head verlinkt. Für die meisten Standard-Anwendungsfälle einer PWA mit Vue ist diese Grundkonfiguration bereits ausreichend, um Lighthouse-Anforderungen für Installierbarkeit zu erfüllen.

3. Das Web-App-Manifest: Installierbarkeit steuern

Das Web-App-Manifest ist eine JSON-Datei, die dem Betriebssystem mitteilt, wie eine Vue-PWA nach der Installation aussehen und sich verhalten soll. Felder wie name, icons und start_url sind Pflichtfelder für die Installierbarkeit, während display: standalone dafür sorgt, dass die App ohne Browser-Chrome wie Adressleiste und Tabs geöffnet wird, was das native Erscheinungsbild erheblich verbessert.

Ein häufig übersehenes Detail sind Maskable Icons: Android beschneidet App-Icons in unterschiedliche Formen, je nach Hersteller-Skin, rund, quadratisch mit abgerundeten Ecken oder als Tropfen. Ein Icon mit dem Zusatz purpose: maskable im Manifest signalisiert dem Betriebssystem, dass ausreichend Sicherheitsabstand zum Rand vorhanden ist, damit wichtige visuelle Elemente nicht abgeschnitten werden.


{
  "name": "Mironsoft App",
  "short_name": "Mironsoft",
  "description": "Produktkatalog und Kundenverwaltung",
  "start_url": "/?source=pwa",
  "display": "standalone",
  "theme_color": "#16a34a",
  "background_color": "#0f172a",
  "orientation": "portrait",
  "icons": [
    { "src": "icon-192.png", "sizes": "192x192", "type": "image/png" },
    { "src": "icon-512.png", "sizes": "512x512", "type": "image/png" },
    { "src": "icon-maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" }
  ]
}

Das Feld start_url mit dem Query-Parameter ?source=pwa ist ein nützliches Muster, um in der Analyse später unterscheiden zu können, ob ein Seitenaufruf von der installierten Vue-PWA oder vom regulären Browser stammt. Diese Information ist wertvoll, um zu verstehen, wie stark die installierte App gegenüber der Browser-Version tatsächlich genutzt wird.

4. Caching-Strategien: Cache First, Network First, Stale While Revalidate

Der Kern jeder PWA mit Vue ist die Entscheidung, welche Caching-Strategie für welche Art von Ressource sinnvoll ist. Statische Assets wie CSS, JavaScript und Bilder ändern sich nur bei einem neuen Deployment und eignen sich daher für die Strategie Cache First: Der Service Worker liefert die Ressource direkt aus dem Cache, ohne überhaupt eine Netzwerkanfrage zu starten, was sowohl Ladezeit als auch Datenverbrauch reduziert.

Für API-Antworten, die sich häufiger ändern, ist Network First oder Stale While Revalidate meist passender. Network First versucht zuerst das Netzwerk und fällt nur bei einem Fehler auf den Cache zurück, was aktuelle Daten priorisiert, aber bei langsamer Verbindung Wartezeit verursacht. Stale While Revalidate liefert sofort die gecachte Version und aktualisiert den Cache im Hintergrund für den nächsten Aufruf, was einen guten Kompromiss zwischen Geschwindigkeit und Aktualität darstellt.


// vite.config.js — workbox runtime caching configuration
VitePWA({
  workbox: {
    runtimeCaching: [
      {
        // Static assets: served instantly, never re-fetched until a new build
        urlPattern: /\.(?:png|jpg|jpeg|svg|webp|woff2)$/,
        handler: 'CacheFirst',
        options: {
          cacheName: 'static-assets',
          expiration: { maxEntries: 100, maxAgeSeconds: 60 * 60 * 24 * 30 },
        },
      },
      {
        // Product API: prefer fresh data, but survive brief network drops
        urlPattern: /^https:\/\/api\.mironsoft\.de\/products/,
        handler: 'NetworkFirst',
        options: {
          cacheName: 'products-api',
          networkTimeoutSeconds: 3,
          expiration: { maxEntries: 50, maxAgeSeconds: 60 * 60 },
        },
      },
      {
        // Dashboard stats: show cached data instantly, refresh silently
        urlPattern: /^https:\/\/api\.mironsoft\.de\/dashboard/,
        handler: 'StaleWhileRevalidate',
        options: { cacheName: 'dashboard-api' },
      },
    ],
  },
})

Die Wahl der richtigen Strategie ist keine rein technische Entscheidung, sondern hängt vom fachlichen Kontext ab. Ein Preis in einem Onlineshop sollte niemals mit Cache First ausgeliefert werden, weil veraltete Preise zu Bestellfehlern führen können. Ein statisches Firmen-Logo dagegen ändert sich praktisch nie und profitiert maximal von aggressivem Caching. Diese fachliche Einordnung sollte vor der technischen Konfiguration jeder Vue-PWA stehen.

5. Offline-Verhalten gezielt gestalten statt dem Zufall überlassen

Eine PWA mit Vue ohne durchdachtes Offline-Verhalten zeigt im besten Fall eine generische Browser-Fehlerseite, im schlechtesten Fall eine leere, verwirrende Ansicht. Eine dedizierte Offline-Fallback-Seite, die der Service Worker ausliefert, sobald sowohl Netzwerk als auch Cache keine Antwort liefern können, verbessert die Nutzererfahrung erheblich und erklärt klar, dass gerade keine Verbindung besteht.

Zusätzlich lohnt es sich, im Vue-Router selbst den Online-Status zu berücksichtigen, etwa über das navigator.onLine-Property in Kombination mit den online- und offline-Events des Browsers. Eine globale Statusanzeige, die den Verbindungsstatus reaktiv widerspiegelt, verhindert, dass Nutzer versuchen, Aktionen auszuführen, die zwangsläufig fehlschlagen werden, weil keine Netzwerkverbindung besteht.


// composables/useOnlineStatus.js
import { ref, onMounted, onUnmounted } from 'vue'

export function useOnlineStatus() {
  const isOnline = ref(navigator.onLine)

  function updateStatus() {
    isOnline.value = navigator.onLine
  }

  onMounted(() => {
    window.addEventListener('online', updateStatus)
    window.addEventListener('offline', updateStatus)
  })

  onUnmounted(() => {
    window.removeEventListener('online', updateStatus)
    window.removeEventListener('offline', updateStatus)
  })

  return { isOnline }
}

Ein wichtiger Aspekt bei Vue-PWA-Anwendungen mit Formularen: Statt eine fehlgeschlagene Anfrage einfach mit einer Fehlermeldung zu quittieren, kann eine Background-Sync-Strategie den Request zwischenspeichern und automatisch erneut senden, sobald die Verbindung zurückkehrt. Das erfordert zusätzliche Logik über die Workbox Background Sync API, verbessert aber die Nutzererfahrung bei instabilen Verbindungen erheblich.

6. Update-Handling: neue Versionen ohne Nutzerverwirrung ausliefern

Ein oft unterschätztes Problem bei einer PWA mit Vue: Der Service Worker cacht eine Version der Anwendung so effektiv, dass Nutzer nach einem Deployment möglicherweise tagelang die alte Version sehen, weil der neue Service Worker zwar im Hintergrund installiert, aber erst nach einem vollständigen Schließen aller Tabs aktiviert wird. Ohne aktives Update-Handling bleibt diese Verzögerung für Nutzer unsichtbar und verwirrend.

Die registrierte registerType: 'prompt'-Option aus Abschnitt zwei gibt der Anwendung die Kontrolle zurück: Statt den Service Worker automatisch zu aktualisieren, liefert vite-plugin-pwa ein virtuelles Modul, über das die Vue-Anwendung erkennt, wann eine neue Version verfügbar ist, und dem Nutzer aktiv einen Hinweis anzeigen kann, bevor die Aktualisierung angestoßen wird.


// composables/usePwaUpdate.js
import { ref } from 'vue'
import { registerSW } from 'virtual:pwa-register'

export function usePwaUpdate() {
  const updateAvailable = ref(false)
  let updateSW

  updateSW = registerSW({
    onNeedRefresh() {
      updateAvailable.value = true // show a toast/banner in the UI
    },
    onOfflineReady() {
      console.log('App ready to work offline')
    },
  })

  function applyUpdate() {
    updateSW(true) // reloads the page with the new service worker active
  }

  return { updateAvailable, applyUpdate }
}

In der Praxis zeigt man bei updateAvailable === true einen dezenten Banner mit einem Text wie "Neue Version verfügbar" und einem Button, der applyUpdate auslöst. Dieses Muster stellt sicher, dass Nutzer einer Vue-PWA nicht überraschend während einer laufenden Eingabe unterbrochen werden, sondern selbst entscheiden, wann der Reload für die neue Version stattfindet.

7. API-Daten offline verfügbar machen mit IndexedDB

Reines HTTP-Caching über den Service Worker reicht für einfache, wiederholbare GET-Anfragen aus, stößt aber an Grenzen, sobald eine Vue-PWA strukturierte Daten offline durchsuchbar oder filterbar machen soll. IndexedDB ist die Browser-Datenbank der Wahl für solche Fälle, weil sie im Gegensatz zu localStorage größere Datenmengen, Indizes für Abfragen und asynchrone Zugriffe unterstützt.

Die Bibliothek Dexie.js vereinfacht die Arbeit mit IndexedDB erheblich gegenüber der rohen, recht umständlichen nativen API. In Kombination mit einem Pinia-Store lässt sich ein Muster etablieren, bei dem Daten zuerst aus IndexedDB geladen werden, während im Hintergrund eine aktuelle Version vom Server nachgeladen und der lokale Datenbestand aktualisiert wird.


// stores/useProductStore.js — Pinia store backed by IndexedDB via Dexie
import { defineStore } from 'pinia'
import Dexie from 'dexie'

const db = new Dexie('mironsoft-db')
db.version(1).stores({ products: 'id, name, category' })

export const useProductStore = defineStore('products', {
  state: () => ({ products: [] }),
  actions: {
    async loadProducts() {
      // Show cached data immediately, even fully offline
      this.products = await db.products.toArray()

      try {
        const response = await fetch('https://api.mironsoft.de/products')
        const fresh = await response.json()
        this.products = fresh
        await db.products.clear()
        await db.products.bulkPut(fresh) // persist for the next offline session
      } catch {
        // Network failed, the IndexedDB snapshot from above stays in use
      }
    },
  },
})

8. Installation-Prompts und Nutzerführung

Chrome und Edge lösen das beforeinstallprompt-Event aus, sobald ihre internen Heuristiken eine Vue-PWA als installationswürdig einstufen, üblicherweise nach wiederholten Besuchen und einem gültigen Manifest samt Service Worker. Dieses Event lässt sich abfangen, um einen eigenen, ins Design integrierten Install-Button anzubieten, statt sich auf den browsereigenen Install-Hinweis zu verlassen, der leicht übersehen wird.

Safari auf iOS unterstützt dieses Event nicht und bietet stattdessen nur den manuellen Weg über "Zum Home-Bildschirm hinzufügen" im Teilen-Menü. Für iOS-Nutzer lohnt sich daher eine dezente, kontextsensitive Anleitung, die genau diesen Weg erklärt, weil ohne Hinweis viele Nutzer die Installationsmöglichkeit auf iOS schlicht nicht entdecken.


// composables/useInstallPrompt.js
import { ref, onMounted } from 'vue'

export function useInstallPrompt() {
  const deferredPrompt = ref(null)
  const canInstall = ref(false)

  onMounted(() => {
    window.addEventListener('beforeinstallprompt', (event) => {
      event.preventDefault() // suppress the browser's default mini-infobar
      deferredPrompt.value = event
      canInstall.value = true
    })
  })

  async function promptInstall() {
    if (!deferredPrompt.value) return
    deferredPrompt.value.prompt()
    const { outcome } = await deferredPrompt.value.userChoice
    canInstall.value = false
    deferredPrompt.value = null
    return outcome // 'accepted' or 'dismissed'
  }

  return { canInstall, promptInstall }
}

9. PWA im Vergleich zu Capacitor für native Distribution

Eine PWA mit Vue ist nicht immer die richtige Wahl für jedes Projekt. Die Entscheidung zwischen PWA und einem nativen Wrapper wie Capacitor hängt stark davon ab, welche Vertriebswege und welche native Funktionalität tatsächlich benötigt werden.

Kriterium PWA mit Vue Vue mit Capacitor
Distribution Direkt per URL, kein Store-Review App Store und Play Store, Review nötig
Update-Geschwindigkeit Sofort nach Deployment Store-Review-Zeit für native Updates
Native APIs Begrenzt auf Web-APIs Voller Zugriff über Plugins
iOS-Installierbarkeit Nur manuell über Teilen-Menü Regulärer App-Store-Eintrag
Entwicklungsaufwand Minimal, gleiche Codebasis Zusätzlicher nativer Build-Prozess

Für interne Business-Tools, Content-lastige Anwendungen oder Projekte mit begrenztem Budget ist eine PWA mit Vue oft die schnellere und günstigere Lösung, weil weder Store-Gebühren noch Review-Prozesse anfallen und Updates sofort bei allen Nutzern ankommen. Sobald ein Projekt jedoch auf Store-Präsenz für Marketing-Zwecke angewiesen ist oder tiefen Zugriff auf native Hardware-Funktionen benötigt, ist Capacitor die passendere Wahl, wie im ersten Artikel dieser Reihe beschrieben.

Mironsoft

Vue-Entwicklung, Progressive Web Apps und Offline-Architektur

Ihre Vue-Anwendung installierbar und offline-fähig?

Wir richten Service Worker, Manifest und Caching-Strategien für Ihre Vue-Anwendung ein, konfigurieren sauberes Update-Handling und sorgen für ein durchdachtes Offline-Erlebnis statt zufälligem Verhalten.

PWA-Setup

vite-plugin-pwa konfigurieren, Manifest und Icons bereitstellen

Caching-Strategie

Passende Strategie pro Ressourcentyp fachlich und technisch festlegen

Offline-UX

Fallback-Seiten, Statusanzeigen und Update-Banner umsetzen

10. Zusammenfassung

Eine PWA mit Vue verwandelt eine bestehende Vue-Anwendung mit vergleichsweise geringem Aufwand in eine installierbare, offline-fähige App. vite-plugin-pwa automatisiert die Generierung von Service Worker und Web-App-Manifest, während Workbox-basierte Caching-Strategien wie Cache First, Network First und Stale While Revalidate je nach Ressourcentyp gezielt konfiguriert werden sollten, statt eine einzige Strategie für alles zu verwenden.

Durchdachtes Offline-Verhalten mit dedizierter Fallback-Seite, aktives Update-Handling mit Nutzerbenachrichtigung statt stiller Aktualisierung, und IndexedDB für offline durchsuchbare Daten heben eine Vue-PWA von einer bloßen technischen Übung zu einer tatsächlich nutzbaren Offline-Erfahrung. Gegenüber Capacitor bleibt die PWA die schnellere, store-freie Alternative für Projekte ohne Bedarf an tiefem nativem Funktionszugriff.

PWA mit Vue und Vite — Das Wichtigste auf einen Blick

Setup

vite-plugin-pwa generiert Service Worker und Manifest automatisch bei jedem Build.

Caching-Strategien

Cache First für statische Assets, Network First oder Stale While Revalidate für API-Daten.

Update-Handling

registerType: prompt gibt der App die Kontrolle über den Zeitpunkt der Aktualisierung.

Offline-Daten

IndexedDB via Dexie.js für strukturierte, offline durchsuchbare API-Daten.

11. FAQ: PWA mit Vue und Vite

1Was braucht eine Vue-App als PWA?
Einen Service Worker, ein Web-App-Manifest und eine HTTPS-Verbindung.
2Schnellster PWA-Einstieg?
Über vite-plugin-pwa, das Service Worker und Manifest automatisch aus der Vite-Konfiguration generiert.
3Caching-Strategie für API-Daten?
Network First oder Stale While Revalidate, je nach Toleranz für kurzfristig veraltete Daten.
4Warum alte Version nach Deployment?
Der Service Worker aktiviert sich erst nach Schließen aller Tabs, ohne aktives Update-Handling mit registerType prompt.
5Update-Hinweis für Nutzer anzeigen?
Über virtual:pwa-register und dessen onNeedRefresh-Callback für einen Banner oder Toast.
6Strukturierte Daten offline durchsuchbar?
Über IndexedDB, idealerweise mit Dexie.js zur Vereinfachung der nativen API.
7Installation auf iOS wie auf Android?
Nein, iOS Safari unterstützt kein beforeinstallprompt, nur den manuellen Weg über das Teilen-Menü.
8Was ist ein Maskable Icon?
Ein Icon mit Sicherheitsabstand, damit Android-Beschneidung in verschiedene Formen nichts Wichtiges abschneidet.
9Sollte jede App eine PWA sein?
Nicht zwingend, bei Bedarf an tiefem nativem Zugriff ist Capacitor oft passender.
10Offline-Verhalten testen?
Über devOptions.enabled im Dev-Server oder den Offline-Modus in den Chrome DevTools.