Frontend og brugeroplevelse

Hvad er en PWA, og hvornår er det en god idé?

En Progressive Web App er stadig en webapp, men den kan få app-lignende egenskaber: installation på startskærmen, eget ikon, separat vindue, hurtig genåbning og udvalgte funktioner uden stabil internetforbindelse. PWA er en måde at forbedre webappen gradvist – ikke en automatisk genvej til en fuld native app.

Det korte svar

En PWA bruger almindelige webteknologier og én URL. På understøttede enheder kan brugeren installere den og åbne den som en app. På andre browsere fungerer den fortsat som et website. Det er selve idéen i “progressive”: kernefunktionen må ikke afhænge af, at alle browsere understøtter alle ekstra muligheder.

En PWA er ikke lig med offline. Et manifest gør appen genkendelig og installérbar. En service worker kan tilføje caching, offline-sider, push og baggrundsarbejde, men hver funktion skal designes og testes særskilt.

Hvornår er en PWA et godt valg?

  • Brugerne vender tilbage ofte: Et ikon og en selvstændig appoplevelse gør et internt værktøj, en portal eller bookingløsning lettere at åbne.
  • Én løsning skal dække mange enheder: Samme kodebase kan fungere på mobil, tablet og desktop, uden separate iOS- og Android-apps.
  • Netværket er ustabilt: En gennemtænkt offline- eller “dårlig forbindelse”-oplevelse kan bevare appens skal og udvalgte arbejdsgange.
  • Hurtig distribution er vigtig: Brugerne får webopdateringer via URL'en uden en traditionel app-store-udgivelse.
  • Appen er primært formularer, data og indhold: Mange virksomhedsapps har ikke behov for dyb adgang til enhedens hardware.

Hvornår bør I vælge noget andet?

En almindelig webapp er nok

Hvis løsningen bruges sjældent, kun online og primært via links eller søgning, kan installation, offline-cache og opdateringslogik være unødvendig kompleksitet.

En native app passer bedre

Hvis kernefunktionen kræver platformsspecifik hardware, vedvarende baggrundsarbejde, avanceret Bluetooth, meget høj grafikydelse eller ensartede funktioner på alle enheder.

Browserunderstøttelse og installationsflow varierer. På iPhone og iPad sker installation typisk via browserens delingsmenu, og visse funktioner kræver, at webappen er føjet til hjemmeskærmen. Test derfor den konkrete funktion på de enheder, målgruppen faktisk bruger.

De tre vigtigste dele

  1. 1. En god responsiv webapp: Den vigtigste arbejdsgang skal først fungere hurtigt, tilgængeligt og sikkert i browseren.
  2. 2. Et web app manifest: En JSON-fil beskriver navn, startadresse, visning, farver og ikoner, så browser og operativsystem ved, hvordan appen skal installeres.
  3. 3. En service worker: Et separat script kan opsnappe netværkskald, styre cache og håndtere blandt andet offline-fallback og push-beskeder.

Produktion skal serveres via HTTPS. Lokal udvikling på localhost er undtaget, så service workers kan testes lokalt.

Et manifest, der passer til appen

public/manifest.webmanifest
{
  "name": "Firmaets arbejdsapp",
  "short_name": "Arbejdsapp",
  "start_url": "/?source=pwa",
  "scope": "/",
  "display": "standalone",
  "background_color": "#0f172a",
  "theme_color": "#0891b2",
  "icons": [
    { "src": "/icons/icon-192.png", "sizes": "192x192", "type": "image/png" },
    { "src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png" },
    { "src": "/icons/icon-maskable-512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" }
  ]
}
  • Brug rigtige ikoner i mindst 192×192 og 512×512 pixels, og test et maskable ikon på forskellige platforme.
  • Sæt start_url og scope, så installerede brugere lander det rigtige sted og bliver i appens relevante URL-område.
  • Brug display: "standalone", hvis løsningen skal åbne uden browserens normale adressefelt.
  • Link manifestet fra alle relevante HTML-sider med <link rel="manifest" href="/manifest.webmanifest" />.

Vælg offline-strategi efter data

Cache ikke alt. En app-shell, statiske assets og en offline-side er noget andet end kundeoplysninger, priser og brugerens seneste API-svar. Vælg strategi pr. type indhold:

  • Cache first: God til versionsnavngivne CSS-, JavaScript- og billedfiler, som sjældent ændrer indhold under samme URL.
  • Network first: God til data, hvor friskhed er vigtig, men et tidligere svar kan bruges ved netværksfejl.
  • Network only: Brug til følsomme eller kritiske handlinger, som ikke må genafspilles eller vises forældet.
  • Offline-kø: Kræver eksplicit status, idempotens og konflikthåndtering. “Gem senere” må ikke skabe dobbelte ordrer eller overskrive nyere data.
Minimal service worker med offline-side
const CACHE = "app-shell-v3";
const APP_SHELL = ["/", "/offline.html", "/assets/app.css"];

self.addEventListener("install", (event) => {
  event.waitUntil(caches.open(CACHE).then((cache) => cache.addAll(APP_SHELL)));
});

self.addEventListener("activate", (event) => {
  event.waitUntil(
    caches.keys().then((keys) =>
      Promise.all(keys.filter((key) => key !== CACHE).map((key) => caches.delete(key)))
    )
  );
});

self.addEventListener("fetch", (event) => {
  if (event.request.mode !== "navigate") return;
  event.respondWith(fetch(event.request).catch(() => caches.match("/offline.html")));
});

Eksemplet er bevidst begrænset til navigation og en offline-side. I en rigtig build-pipeline bør filnavne og cacheversioner genereres ud fra de assets, der faktisk er udgivet.

Opdateringer må ikke overraske brugeren

En service worker kan fortsætte med at levere en ældre version, mens en ny venter på at blive aktiveret. Det beskytter åbne faner, men kan også give en frontend, der ikke matcher backendens API.

  • Vis en forståelig “Ny version er klar”-besked, når en opdatering venter.
  • Genindlæs først på et sikkert tidspunkt – ikke midt i en formular eller betaling.
  • Hold backend-API'er bagudkompatible under udrulningen.
  • Versionér caches, og fjern gamle caches i service workerens activate-fase.
  • Test opgradering fra den tidligere produktionsversion – ikke kun en ren installation.

Installation og push skal være brugerens valg

Bed først om installation, når brugeren har oplevet værdien af appen. Forklar hvordan appen installeres på den aktuelle platform, men behold altid den almindelige browseroplevelse.

Push-beskeder bør kun bruges til vigtige og tidsrelevante hændelser. Bed om tilladelse efter en tydelig brugerhandling, og giv mulighed for at vælge typer og slå dem fra. Apple understøtter Web Push til hjemmeskærmswebapps fra iOS/iPadOS 16.4, men det gør ikke support ens på tværs af alle browsere og versioner.

Sikkerhed og persondata

  • Cache er lokal lagring: Undgå persondata og følsomme API-svar, medmindre risiko, kryptering, logout og sletning er håndteret.
  • Offline er ikke login: En cached side må ikke give adgang til data, som brugeren ikke længere har rettighed til.
  • Service workeren har stor rækkevidde: Begræns dens scope, og beskyt deployment, headers og kildekode som anden kritisk frontendkode.
  • Push indeholder data: Undgå følsomt indhold på en låseskærm, og valider abonnementer på serveren.
  • Ryd op ved logout: Fjern brugerrelateret cache og lokal data, især på delte enheder.

Sådan tester I en PWA ordentligt

  • Test installation og afinstallation på Android, iOS/iPadOS og relevante desktopbrowsere.
  • Test første besøg, genbesøg, langsomt netværk, helt offline og netværk der forsvinder midt i en handling.
  • Test ny deployment oven på den gamle version med åbne faner og ufærdige formularer.
  • Kontrollér ikoner, start-URL, deep links, tilbageknap, login og logout i installeret tilstand.
  • Kontrollér tastatur, skærmlæser, zoom, fokus og store trykflader.
  • Brug browsernes PWA-/Application-værktøjer og automatiske audits som hjælp – ikke som eneste godkendelse.

Typiske PWA-fejl

  • “Cache alt”: Brugeren får gamle data, og cache vokser uden kontrol.
  • Offline markedsføres, men kun forsiden virker: Den vigtige arbejdsgang fejler stadig uden netværk.
  • Ingen opdateringsoplevelse: Brugeren sidder fast på gammel frontend eller mister indtastede data ved tvungen reload.
  • PWA vælges for at “komme i app stores”: Målgruppens behov, installation og enhedsfunktioner er ikke undersøgt først.
  • Kun testet i én Chromium-browser: Installation, push, storage og baggrundsfunktioner antages at være ens på iPhone og desktop.
  • Cache overlever logout: Den næste bruger på en delt enhed kan se tidligere data.

Tjekliste før I kalder løsningen en PWA

  • □ Kernefunktionen virker som responsiv webapp uden installation.
  • □ Manifest, ikoner, start-URL, scope og display er testet på rigtige enheder.
  • □ Produktionssitet bruger HTTPS.
  • □ Offline-strategien er besluttet pr. data- og requesttype.
  • □ Følsomme data bliver ikke cached ved et uheld og ryddes ved logout.
  • □ Opdatering fra forrige version er testet uden datatab.
  • □ Installation og notifikationer præsenteres på et relevant tidspunkt.
  • □ De vigtigste flows er testet på målgruppens browsere og enheder.
  • □ Monitoring kan skelne mellem netværks-, cache- og versionsfejl.

Relaterede guides

Officielle kilder

PWA-funktioner varierer mellem browsere og ændres løbende. Kontrollér derfor support for de konkrete funktioner på målgruppens enheder.