PWA: podstawy Progressive Web App, Service Worker i manifest

Autor: IT Sectr Opublikowano: 2026-02-14 Czas czytania: 10 min

PWA (Progressive Web App) to aplikacja internetowa, która wykorzystuje nowoczesne możliwości przeglądarki, aby działać jak natywna aplikacja: szybko się ładuje, działa offline, wysyła powiadomienia push i instaluje się na ekranie głównym. U podstaw PWA leżą trzy technologie: Service Worker, manifest i HTTPS. Service Worker to skrypt uruchamiany przez przeglądarkę w tle, niezależnie od strony internetowej, otwierający możliwości niedostępne dla zwykłych witryn: przechwytywanie żądań sieciowych, buforowanie zasobów, synchronizacja w tle i powiadomienia push. Manifest to plik JSON, który informuje przeglądarkę, jak aplikacja powinna wyglądać po zainstalowaniu na urządzeniu: nazwa, ikony, kolor motywu, orientacja ekranu. Bez HTTPS Service Worker nie działa — to obowiązkowy wymóg bezpieczeństwa. PWA są kompatybilne z każdą nowoczesną przeglądarką i nie wymagają publikacji w sklepie z aplikacjami. Użytkownik otwiera stronę, widzi propozycję instalacji aplikacji, klika «Dodaj do ekranu głównego» — i aplikacja jest gotowa. Dla biznesu PWA oznacza zasięg każdej publiczności bez kosztów rozwoju osobno dla iOS i Android, wysoką szybkość ładowania nawet w wolnych sieciach oraz zaangażowanie przez powiadomienia push. W artykule omówimy, jak działa Service Worker, jak stworzyć manifest, jakie strategie buforowania stosować i jak zapewnić dostęp offline.

Najważniejsze

  • PWA — aplikacja internetowa działająca jak natywna: instaluje się na ekranie głównym, działa offline, wysyła powiadomienia push
  • Service Worker — skrypt JS działający w tle z cyklem życia: rejestracja, instalacja, aktywacja, przechwytywanie żądań sieciowych
  • Strategie buforowania — Cache First, Network First, Stale While Revalidate dla różnych typów zasobów
  • Web App Manifest — plik JSON z ustawieniami nazwy, ikon, koloru motywu i trybu wyświetlania
  • Powiadomienia push — działają przez Push API i Notification API nawet przy zamkniętej aplikacji
  • Lighthouse — narzędzie audytu PWA z minimalnym progiem zaliczenia 80 na 100
  • Workbox — biblioteka Google ułatwiająca tworzenie i zarządzanie Service Worker

Najważniejsze

  • PWA — aplikacja internetowa działająca jak natywna: instaluje się na ekranie głównym, działa offline, wysyła powiadomienia push
  • Service Worker — skrypt JS działający w tle z cyklem życia: rejestracja, instalacja, aktywacja, przechwytywanie żądań sieciowych
  • Strategie buforowania — Cache First, Network First, Stale While Revalidate dla różnych typów zasobów
  • Web App Manifest — plik JSON z ustawieniami nazwy, ikon, koloru motywu i trybu wyświetlania
  • Powiadomienia push — działają przez Push API i Notification API nawet przy zamkniętej aplikacji
  • Lighthouse — narzędzie audytu PWA z minimalnym progiem zaliczenia 80 na 100
  • Workbox — biblioteka Google ułatwiająca tworzenie i zarządzanie Service Worker

Co to jest Progressive Web App

Progressive Web App (PWA) to podejście do tworzenia aplikacji internetowych, które łączy najlepsze cechy sieci i aplikacji natywnych. Termin został wprowadzony przez Francesca Berrimana w 2015 roku, a Google aktywnie promuje PWA jako zamiennik prostych aplikacji mobilnych. Główna idea: strona internetowa stopniowo ulepsza się w zależności od możliwości przeglądarki i urządzenia. Jeśli przeglądarka obsługuje Service Worker — włącza się tryb offline. Jeśli obsługuje manifest — pojawia się przycisk «Zainstaluj». Jeśli dostępne jest API powiadomień — aplikacja może wysyłać push. Użytkownik na słabym urządzeniu z wolnym internetem otrzyma podstawową wersję strony, a na nowoczesnym smartfonie — pełnoprawną aplikację z ikoną na pulpicie.

PWA nie wymaga instalacji przez sklep z aplikacjami. Wystarczy link. To rozwiązuje główny problem aplikacji mobilnych — wysoki próg wejścia. Użytkownik nie idzie do Google Play lub App Store, nie czeka na pobranie 100 MB, nie udziela dziesięciu uprawnień. Po prostu otwiera stronę, a przeglądarka proponuje zainstalowanie aplikacji. Jeśli użytkownik odmówi — nadal korzysta ze strony. A jeśli się zgodzi — ikona pojawia się na ekranie głównym, a aplikacja otwiera się jak natywna: bez paska adresu przeglądarki, w trybie pełnoekranowym i z szybkim uruchomieniem.

Technicznie PWA musi spełniać trzy kryteria: działać przez HTTPS (bezpieczne połączenie), mieć Service Worker (skrypt przetwarzania w tle) i zawierać manifest (Web App Manifest). Te trzy komponenty zamieniają zwykłą stronę w instalowalną aplikację.

Service Worker: serce PWA

Service Worker to skrypt JavaScript, który przeglądarka uruchamia w osobnym wątku, niezależnie od strony internetowej. Nie ma dostępu do DOM, nie może bezpośrednio interagować z interfejsem, ale może przechwytywać i modyfikować żądania sieciowe, zarządzać pamięcią podręczną, obsługiwać powiadomienia push i wykonywać synchronizację w tle. Service Worker działa jak serwer proxy między przeglądarką a siecią: każde żądanie ze strony przechodzi przez Service Worker, który decyduje — zwrócić dane z pamięci podręcznej, zapytać serwer lub zrobić jedno i drugie.

Service Worker żyje według własnego cyklu życia, niezwiązanego z otwartą stroną. Jest instalowany, aktywowany i działa w tle nawet po zamknięciu wszystkich kart witryny. Pozwala to PWA otrzymywać powiadomienia push i aktualizować pamięć podręczną w tle, bez udziału użytkownika.

Cykl życia Service Worker

Service Worker przechodzi cztery etapy: rejestracja, instalacja, aktywacja oraz bezczynność/zakończenie.

Rejestracja. Przeglądarka otrzymuje link do pliku JS Service Worker i rozpoczyna pobieranie. Rejestracja jest wykonywana ze zwykłego JavaScript na stronie:

javascript
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js')
    .then(registration => {
      console.log('SW zarejestrowany:', registration.scope);
    })
    .catch(error => {
      console.log('Rejestracja SW nie powiodła się:', error);
    });
}

Instalacja. Po pomyślnym pobraniu przeglądarka uruchamia zdarzenie install. Na tym etapie zwykle buforuje się kluczowe zasoby (szkielet HTML, CSS, główne obrazy), aby aplikacja mogła działać offline. Jeśli instalacja się powiedzie, Service Worker przechodzi do następnego etapu. Jeśli skrypt zgłosi błąd — instalacja jest anulowana, a stary Service Worker nadal działa.

javascript
self.addEventListener('install', event => {
  event.waitUntil(
    caches.open('pwa-cache-v1').then(cache => {
      return cache.addAll([
        '/',
        '/index.html',
        '/styles/main.css',
        '/scripts/app.js',
        '/images/logo.png'
      ]);
    })
  );
});

Aktywacja. Gdy wszystkie karty witryny są zamknięte, stary Service Worker kończy działanie, a nowy zostaje aktywowany. Zdarzenie activate jest używane do czyszczenia starych pamięci podręcznych i migracji danych:

javascript
self.addEventListener('activate', event => {
  const cacheWhitelist = ['pwa-cache-v2'];
  event.waitUntil(
    caches.keys().then(cacheNames => {
      return Promise.all(
        cacheNames.map(cacheName => {
          if (!cacheWhitelist.includes(cacheName)) {
            return caches.delete(cacheName);
          }
        })
      );
    })
  );
});

Bezczynność. Aktywowany Service Worker przechwytuje żądania i obsługuje zdarzenia. Może zostać zatrzymany przez przeglądarkę w celu oszczędzania zasobów i ponownie uruchomiony przy następnym żądaniu. Service Worker jest sterowany zdarzeniami: żyje tylko podczas przetwarzania zdarzeń.

Strategie buforowania

Service Worker obsługuje kilka strategii buforowania. Wybór zależy od typu zasobu i wymagań dotyczących aktualności danych.

Cache First (najpierw pamięć podręczna). Najpierw sprawdzana jest pamięć podręczna. Jeśli zasób zostanie znaleziony — zwracany jest z pamięci podręcznej. Jeśli nie — żądanie trafia na serwer, odpowiedź jest zapisywana w pamięci podręcznej. Strategia nadaje się do zasobów statycznych: obrazy, czcionki, CSS, JS. Zapewnia maksymalną szybkość i pełną pracę offline.

javascript
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(response => {
      return response || fetch(event.request).then(fetchResponse => {
        return caches.open('pwa-cache-v1').then(cache => {
          cache.put(event.request, fetchResponse.clone());
          return fetchResponse;
        });
      });
    })
  );
});

Network First (najpierw sieć). Żądanie najpierw trafia na serwer. Jeśli serwer odpowiedział — dane są zwracane użytkownikowi i zapisywane w pamięci podręcznej. Jeśli serwer jest niedostępny — zwracana jest zapisana w pamięci podręcznej kopia. Strategia nadaje się do żądań API, wiadomości, treści, które muszą być aktualne, ale mogą działać również offline.

javascript
self.addEventListener('fetch', event => {
  event.respondWith(
    fetch(event.request).then(response => {
      return caches.open('pwa-dynamic-v1').then(cache => {
        cache.put(event.request, response.clone());
        return response;
      });
    }).catch(() => {
      return caches.match(event.request);
    })
  );
});

Stale While Revalidate (nieaktualne z odświeżeniem). Odpowiedź jest natychmiast zwracana z pamięci podręcznej, a w tle wysyłane jest żądanie na serwer w celu aktualizacji pamięci podręcznej. Użytkownik widzi treść natychmiast, a następne żądanie otrzyma już świeże dane. Idealne dla treści, które się zmieniają, ale nie jest krytyczne, jeśli użytkownik zobaczy wersję o kilka minut starszą.

javascript
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(cached => {
      const fetchPromise = fetch(event.request).then(response => {
        return caches.open('pwa-dynamic-v1').then(cache => {
          cache.put(event.request, response.clone());
          return response;
        });
      });
      return cached || fetchPromise;
    })
  );
});

Web App Manifest: jak aplikacja wygląda na urządzeniu

Manifest to plik JSON, zazwyczaj manifest.json, który jest podłączany przez tag <link> w nagłówku HTML strony. Informuje przeglądarkę, jak aplikacja powinna być wyświetlana po zainstalowaniu na urządzeniu: nazwa, ikony różnych rozmiarów, kolor tła, kolor motywu, orientacja i tryb wyświetlania (przeglądarka, minimalny UI, pełnoekranowy).

json
{
  "name": "PWA Demo App",
  "short_name": "PWA Demo",
  "description": "Demo aplikacji PWA",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#3f51b5",
  "orientation": "portrait",
  "icons": [
    {
      "src": "/icons/icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/icons/icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "any maskable"
    }
  ]
}

Parametr display określa, jak będzie wyglądać aplikacja po instalacji. standalone ukrywa pasek adresu przeglądarki i panel nawigacyjny — aplikacja wygląda jak natywna. fullscreen wykorzystuje cały ekran bez żadnych elementów przeglądarki. minimal-ui pozostawia minimalne elementy przeglądarki (przyciski wstecz i odświeżania).

Ikony powinny być przygotowane w co najmniej dwóch rozmiarach: 192x192 i 512x512 pikseli. Format PNG z obsługą parametru purpose (na przykład maskable) pozwala przeglądarce dostosować ikonę do kształtu obudowy urządzenia — na Androidzie ikona może być przycięta do zaokrąglonego kwadratu. Po podłączeniu manifestu przeglądarka Chrome na Androidzie zaczyna wyświetlać baner «Dodaj do ekranu głównego» po spełnieniu warunków: HTTPS, zarejestrowany Service Worker, poprawny manifest i co najmniej dwie wizyty w odstępie 5 minut.

Powiadomienia push w PWA

PWA może wysyłać powiadomienia push jak natywna aplikacja. Służą do tego dwa API: Push API (wysyłanie serwerowe) i Notification API (wyświetlanie na urządzeniu). Service Worker otrzymuje zdarzenie push nawet jeśli aplikacja nie jest otwarta i może wyświetlić powiadomienie z tytułem, treścią i ikoną.

Aby otrzymywać powiadomienia push, użytkownik musi wyrazić zgodę:

javascript
Notification.requestPermission().then(permission => {
  if (permission === 'granted') {
    console.log('Push dozwolony');
  }
});

Service Worker subskrybuje zdarzenie push i wyświetla powiadomienie:

javascript
self.addEventListener('push', event => {
  const data = event.data.json();
  self.registration.showNotification(data.title, {
    body: data.body,
    icon: '/icons/icon-192x192.png',
    badge: '/icons/badge-72x72.png',
    actions: [
      { action: 'open', title: 'Otwórz' },
      { action: 'close', title: 'Zamknij' }
    ]
  });
});

self.addEventListener('notificationclick', event => {
  event.notification.close();
  if (event.action === 'open') {
    clients.openWindow('/');
  }
});

Do wysyłania push z serwera używany jest protokół Web Push (VAPID). Serwer szyfruje wiadomość i wysyła ją przez przeglądarkową usługę push (Firebase Cloud Messaging dla Chrome, Mozilla Autopush dla Firefox). Subskrypcja użytkownika (obiekt PushSubscription) musi być zapisana na serwerze podczas rejestracji.

Wydajność i Lighthouse

PWA muszą być szybkie. Google Lighthouse to narzędzie audytu, które sprawdza PWA według listy kontrolnej: rejestracja Service Worker, odpowiedź 200 przy dostępie offline, poprawny manifest, HTTPS, prawidłowy rozmiar ikon, szybkie ładowanie w wolnych sieciach. Minimalny próg zaliczenia dla PWA — 80 na 100 w skali Lighthouse. Aplikacje z wynikiem poniżej 80 nie otrzymują banera instalacji w Chrome.

Kluczowe metryki wydajności dla PWA — First Contentful Paint (FCP) do 1.8 sekundy, Largest Contentful Paint (LCP) do 2.5 sekundy, Time to Interactive (TTI) do 3.5 sekundy. Service Worker może znacząco poprawić FCP i LCP, jeśli buforuje krytyczny HTML i CSS podczas instalacji. Strategia Cache First dla statyki i Stale While Revalidate dla API daje najlepsze doświadczenie użytkownika.

Dostęp offline i synchronizacja w tle

Jedną z głównych możliwości PWA jest praca bez internetu. Service Worker przechwytuje żądania i zwraca zapisane w pamięci podręcznej wersje stron. Jeśli użytkownik próbuje otworzyć stronę, której nie ma w pamięci podręcznej, można wyświetlić niestandardową stronę zastępczą:

javascript
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(response => {
      return response || fetch(event.request);
    }).catch(() => {
      return caches.match('/offline.html');
    })
  );
});

Synchronizacja w tle (Background Sync) pozwala odłożyć wysyłanie danych na serwer, jeśli urządzenie jest offline. Service Worker zapisuje żądanie i automatycznie wysyła je, gdy połączenie zostanie przywrócone:

javascript
self.addEventListener('sync', event => {
  if (event.tag === 'sync-messages') {
    event.waitUntil(sendMessages());
  }
});

function sendMessages() {
  return caches.open('pwa-pending-v1').then(cache => {
    return cache.keys().then(requests => {
      return Promise.all(requests.map(request => {
        return fetch(request).then(() => cache.delete(request));
      }));
    });
  });
}

Narzędzia do rozwoju PWA

Chrome DevTools udostępnia panel Application, gdzie można debugować Service Worker (rejestracja, status, pamięć podręczna, push), sprawdzać manifest, czyścić pamięć podręczną i tworzyć własne powiadomienia push do testowania. Zakładka Network z emulacją trybu offline pomaga sprawdzić działanie pamięci podręcznej. Lighthouse w panelu Audits zapewnia pełny audyt PWA z zaleceniami.

Workbox — biblioteka od Google, która upraszcza tworzenie Service Worker. Zamiast ręcznego pisania strategii buforowania, Workbox oferuje gotowe moduły:

javascript
import { precacheAndRoute } from 'workbox-precaching';
import { registerRoute } from 'workbox-routing';
import { StaleWhileRevalidate } from 'workbox-strategies';

precacheAndRoute(self.__WB_MANIFEST);

registerRoute(
  /\.(?:png|jpg|jpeg|svg|gif)$/,
  new StaleWhileRevalidate()
);

Workbox integruje się z bundlerami (Webpack, Vite) i automatycznie generuje manifest wstępnego buforowania. PWA Builder (pwabuilder.com) od Microsoft generuje wszystkie pliki PWA online: Service Worker, manifest, ikony, szablon HTML.

FAQ

Czym jest PWA w prostych słowach?

PWA to strona, która po zainstalowaniu na telefonie działa jak zwykła aplikacja: ma ikonę na pulpicie, dostęp offline, powiadomienia push, tryb pełnoekranowy bez paska adresu przeglądarki. Przy tym nie trzeba iść do App Store ani Google Play — instalacja odbywa się jednym kliknięciem z przeglądarki.

Jaka jest różnica między PWA a natywną aplikacją?

Aplikacja natywna jest pisana pod konkretną platformę (Swift dla iOS, Kotlin dla Android), wymaga publikacji w sklepie i ręcznej instalacji. PWA to strona internetowa napisana w HTML, CSS i JavaScript, która może być zainstalowana na urządzeniu przez przeglądarkę. PWA nie zajmuje dużo miejsca (tylko pamięć podręczna), aktualizuje się automatycznie i jest obsługiwana przez wszystkie nowoczesne przeglądarki.

Które przeglądarki obsługują PWA?

Chrome, Firefox, Safari (od iOS 11.3), Edge, Samsung Internet, Opera. Service Worker jest obsługiwany przez wszystkie nowoczesne przeglądarki z wyjątkiem Internet Explorer. Safari ma ograniczoną obsługę powiadomień push, ale podstawowe możliwości PWA (instalacja na ekranie głównym, dostęp offline) działają.

Czy można przekształcić istniejącą stronę w PWA?

Tak. W tym celu należy dodać manifest (manifest.json), utworzyć i zarejestrować Service Worker (sw.js), przejść na HTTPS, dodać meta tagi i ikony. Sama strona nie wymaga przepisywania, jeśli działa na JavaScript i zwraca HTML. Jeśli strona jest w pełni serwerowa (MPA), można dodać Service Worker jako warstwę buforowania bez zmiany architektury.

Jak aktualizuje się PWA?

Gdy użytkownik otwiera PWA, przeglądarka sprawdza, czy plik Service Worker na serwerze się zmienił. Jeśli plik różni się choćby o bajt, przeglądarka pobiera nowy Service Worker i uruchamia jego instalację. Stary Service Worker nadal działa, dopóki wszystkie karty aplikacji nie zostaną zamknięte. Po zamknięciu kart nowy Service Worker aktywuje się i zastępuje stary. Użytkownik może wymusić aktualizację aplikacji, przeładowując stronę.

Czy warto rozwijać PWA zamiast aplikacji mobilnej?

PWA jest uzasadnione, jeśli celem jest dotarcie do maksymalnej publiczności bez kosztów rozwoju na dwie platformy, jeśli aplikacja nie wymaga głębokiego dostępu do sprzętu (Bluetooth, NFC, kamera w tle), jeśli treść zmienia się często. Dla złożonych aplikacji (gry, edytory wideo) aplikacja natywna pozostaje preferowana. PWA jest często używane jako dodatkowy kanał lub jako MVP przed pełnoprawną aplikacją.

Podsumowanie

  • PWA (Progressive Web App) — aplikacja internetowa działająca jak natywna: instaluje się na ekranie głównym, działa offline, wysyła powiadomienia push.
  • Trzy obowiązkowe komponenty PWA: HTTPS, Service Worker i manifest (manifest.json). Bez któregokolwiek z tych elementów przeglądarka nie zaoferuje instalacji.
  • Service Worker — skrypt JavaScript działający w tle, przechwytujący żądania sieciowe. Realizuje strategie buforowania: Cache First (statyka), Network First (API), Stale While Revalidate (treść z odświeżeniem).
  • Web App Manifest — plik JSON z ustawieniami wyświetlania: nazwa, ikony, kolor motywu, display (standalone, fullscreen, minimal-ui). Ikony potrzebne w rozmiarach 192x192 i 512x512.
  • Powiadomienia push w PWA działają przez Push API i Notification API. Service Worker otrzymuje zdarzenie push nawet przy zamkniętej aplikacji.
  • Lighthouse sprawdza PWA według listy kontrolnej. Minimalny wynik do instalacji — 80 na 100. Kluczowe metryki: FCP do 1.8 s, LCP do 2.5 s.
  • Workbox od Google upraszcza rozwój Service Worker: gotowe strategie, automatyczne buforowanie, integracja z bundlerami.

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również