PWA: พื้นฐาน Progressive Web App, Service Worker และ Manifest

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-02-14 เวลาอ่าน: 10 นาที

PWA (Progressive Web App) is a web application that uses modern browser capabilities to work like a native app: it loads quickly, works offline, sends push notifications and can be installed on the home screen. PWA is built on three technologies: Service Worker, manifest and HTTPS. Service Worker is a script that the browser runs in the background, separately from the web page, enabling capabilities unavailable to regular websites: intercepting network requests, caching resources, background synchronization and push notifications. The manifest is a JSON file that tells the browser how the application should look when installed on a device: name, icons, theme color, screen orientation. Without HTTPS, Service Worker does not work — this is a mandatory security requirement. PWAs are compatible with any modern browser and do not require publication in an app store. The user opens the site, sees an offer to install the application, taps "Add to Home Screen" — and the app is ready. For businesses, PWA means reaching any audience without separate development costs for iOS and Android, fast loading even on slow networks, and engagement through push notifications. In this article, we will explore how Service Worker works, how to create a manifest, which caching strategies to use and how to implement offline access.

Key Takeaways

  • PWA — a web application that works like a native app: installs on the home screen, works offline, sends push notifications
  • Service Worker — a background JS script with a lifecycle: registration, installation, activation, network request interception
  • Caching Strategies — Cache First, Network First, Stale While Revalidate for different resource types
  • Web App Manifest — a JSON file with settings for name, icons, theme color and display mode
  • Push Notifications — work via Push API and Notification API even when the app is closed
  • Lighthouse — PWA audit tool with a minimum passing score of 80 out of 100
  • Workbox — Google library for simplifying Service Worker creation and management

Key Takeaways

  • PWA — a web application that works like a native app: installs on the home screen, works offline, sends push notifications
  • Service Worker — a background JS script with a lifecycle: registration, installation, activation, network request interception
  • Caching Strategies — Cache First, Network First, Stale While Revalidate for different resource types
  • Web App Manifest — a JSON file with settings for name, icons, theme color and display mode
  • Push Notifications — work via Push API and Notification API even when the app is closed
  • Lighthouse — PWA audit tool with a minimum passing score of 80 out of 100
  • Workbox — Google library for simplifying Service Worker creation and management

What is Progressive Web App

Progressive Web App (PWA) is an approach to web application development that combines the best qualities of the web and native apps. The term was coined by Francesco Berriman in 2015, and Google actively promotes PWA as a replacement for simple mobile applications. The main idea: a website progressively improves depending on browser and device capabilities. If the browser supports Service Worker — offline mode is enabled. If it supports the manifest — an "Install" button appears. If the notifications API is available — the app can send push messages. A user on a weak device with a slow internet connection gets the basic version of the site, while on a modern smartphone they get a full-fledged app with an icon on the desktop.

PWAs do not need to be installed through an app store. A link is enough. This solves the main problem of mobile apps — the high entry barrier. The user does not go to Google Play or the App Store, does not wait for a 100 MB download, does not grant a dozen permissions. They simply open the site, and the browser offers to install the app. If the user declines — they still use the site. And if they agree — the icon appears on the home screen, and the app opens like a native one: without the browser address bar, with fullscreen mode and fast launch.

Technically, a PWA must meet three criteria: work over HTTPS (secure connection), have a Service Worker (background processing script) and include a manifest (Web App Manifest). These three components turn a regular website into an installable application.

Service Worker: The Heart of PWA

Service Worker is a JavaScript script that the browser runs in a separate thread, independent of the web page. It does not have access to the DOM, cannot directly interact with the interface, but it can intercept and modify network requests, manage the cache, handle push notifications and perform background synchronization. Service Worker acts as a proxy server between the browser and the network: every request from the page goes through the Service Worker, which decides — to serve data from the cache, request from the server, or do both.

Service Worker has its own lifecycle, not tied to the open page. It installs, activates and runs in the background even after all site tabs are closed. This allows PWAs to receive push notifications and update the cache in the background, without user involvement.

Service Worker Lifecycle

Service Worker goes through four stages: registration, installation, activation and idle/termination.

Registration. The browser receives a link to the Service Worker JS file and begins downloading. Registration is done from regular JavaScript on the page:

javascript
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js')
    .then(registration => {
      console.log('SW registered:', registration.scope);
    })
    .catch(error => {
      console.log('SW registration failed:', error);
    });
}

Installation. After successful download, the browser fires the install event. At this stage, it is common to cache key resources (HTML shell, CSS, main images) so the app can work offline. If the installation succeeds, the Service Worker moves to the next stage. If the script throws an error — installation is cancelled, and the old Service Worker continues to work.

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'
      ]);
    })
  );
});

Activation. When all site tabs are closed, the old Service Worker terminates and the new one activates. The activate event is used to clean up old caches and migrate data:

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);
          }
        })
      );
    })
  );
});

Idle. An activated Service Worker intercepts requests and handles events. It may be stopped by the browser to save resources and restarted on the next request. Service Worker is event-driven: it lives only while processing events.

Caching Strategies

Service Worker supports several caching strategies. The choice depends on the resource type and data freshness requirements.

Cache First. The cache is checked first. If the resource is found — it is returned from cache. If not — the request goes to the server, the response is saved to cache. This strategy is suitable for static resources: images, fonts, CSS, JS. It provides maximum speed and full offline functionality.

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. The request goes to the server first. If the server responds — data is returned to the user and saved to cache. If the server is unavailable — the cached copy is served. This strategy is suitable for API requests, news, content that must be up-to-date but can also work 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. The response is immediately returned from cache, while a background request is sent to the server to update the cache. The user sees content instantly, and the next request will get fresh data. Ideal for content that changes but where it is not critical if the user sees a version that is a few minutes old.

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: How the App Looks on a Device

The manifest is a JSON file, usually manifest.json, linked via a <link> tag in the HTML page head. It tells the browser how the application should display when installed on a device: name, icons of different sizes, background color, theme color, orientation and display mode (browser, minimal UI, fullscreen).

json
{
  "name": "PWA Demo App",
  "short_name": "PWA Demo",
  "description": "แอปพลิเคชัน 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"
    }
  ]
}

The display parameter determines how the app will look after installation. standalone hides the browser address bar and navigation panel — the app looks native. fullscreen uses the entire screen without any browser elements. minimal-ui leaves minimal browser elements (back and refresh buttons).

Icons should be prepared in at least two sizes: 192x192 and 512x512 pixels. PNG format with support for the purpose parameter (e.g., maskable) allows the browser to adapt the icon to the device shell shape — on Android, the icon may be cropped to a rounded square. After connecting the manifest, Chrome on Android starts showing the "Add to Home Screen" banner when conditions are met: HTTPS, registered Service Worker, valid manifest and at least two visits with a 5-minute interval.

Push Notifications in PWA

PWA can send push notifications like a native app. Two APIs are used: Push API (server-side sending) and Notification API (display on device). Service Worker receives the push event even if the app is not open, and can display a notification with a title, text and icon.

To receive push notifications, the user must grant permission:

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

Service Worker subscribes to the push event and displays the notification:

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: 'เปิด' },
      { action: 'close', title: 'ปิด' }
    ]
  });
});

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

To send push from the server, the Web Push protocol (VAPID) is used. The server encrypts the message and sends it through the browser push service (Firebase Cloud Messaging for Chrome, Mozilla Autopush for Firefox). The user's subscription (PushSubscription object) must be saved on the server during registration.

Performance and Lighthouse

PWAs must be fast. Google Lighthouse is an audit tool that checks PWA against a checklist: Service Worker registration, 200 response with offline access, valid manifest, HTTPS, correct icon sizes, fast loading on slow networks. The minimum passing score for PWA is 80 out of 100 on the Lighthouse scale. Apps with a score below 80 do not receive the Chrome install banner.

Key performance metrics for PWAs — First Contentful Paint (FCP) under 1.8 seconds, Largest Contentful Paint (LCP) under 2.5 seconds, Time to Interactive (TTI) under 3.5 seconds. Service Worker can significantly improve FCP and LCP if it caches critical HTML and CSS during installation. The Cache First strategy for static assets and Stale While Revalidate for APIs gives the best user experience.

Offline Access and Background Sync

One of the main capabilities of PWA is working without internet. Service Worker intercepts requests and serves cached versions of pages. If the user tries to open a page that is not in the cache, a custom fallback page can be shown:

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

Background Sync allows deferring data sending to the server if the device is offline. Service Worker saves the request and automatically sends it when the connection is restored:

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));
      }));
    });
  });
}

PWA Development Tools

Chrome DevTools provides the Application panel, where you can debug Service Worker (registration, status, cache, push), check the manifest, clear the cache and create custom push notifications for testing. The Network tab with offline mode emulation helps test cache behavior. Lighthouse in the Audits panel provides a full PWA audit with recommendations.

Workbox is a library from Google that simplifies Service Worker creation. Instead of manually writing caching strategies, Workbox offers ready-made modules:

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 integrates with bundlers (Webpack, Vite) and automatically generates a precaching manifest. PWA Builder (pwabuilder.com) by Microsoft generates all PWA files online: Service Worker, manifest, icons, HTML template.

FAQ

What is PWA in simple terms?

PWA is a website that, after installation on your phone, works like a regular app: it has an icon on the home screen, offline access, push notifications, fullscreen mode without the browser address bar. And you don't need to go to the App Store or Google Play — installation happens in one click from the browser.

What is the difference between PWA and a native app?

A native app is written for a specific platform (Swift for iOS, Kotlin for Android), requires publication in a store and manual installation. PWA is a website written in HTML, CSS and JavaScript that can be installed on a device through the browser. PWA does not take up much space (only cache), updates automatically and is supported by all modern browsers.

Which browsers support PWA?

Chrome, Firefox, Safari (since iOS 11.3), Edge, Samsung Internet, Opera. Service Worker is supported by all modern browsers except Internet Explorer. Safari has limited support for push notifications, but basic PWA capabilities (install to home screen, offline access) work.

Can an existing website be turned into a PWA?

Yes. To do this, you need to add a manifest (manifest.json), create and register a Service Worker (sw.js), switch the site to HTTPS, add meta tags and icons. The site itself does not require rewriting if it runs on JavaScript and serves HTML. If the site is fully server-side (MPA), you can add a Service Worker as a caching layer without changing the architecture.

How does PWA update?

When a user opens a PWA, the browser checks whether the Service Worker file on the server has changed. If the file differs by even one byte, the browser downloads the new Service Worker and runs its installation. The old Service Worker continues to work until all app tabs are closed. After the tabs are closed, the new Service Worker activates and replaces the old one. The user can force update the app by reloading the page.

Should I develop a PWA instead of a mobile app?

PWA is justified if the goal is to reach the maximum audience without development costs for two platforms, if the app does not require deep access to hardware (Bluetooth, NFC, background camera), if content changes frequently. For complex applications (games, video editors), a native app remains preferable. PWA is often used as an additional channel or as an MVP before a full-fledged app.

Summary

  • PWA (Progressive Web App) — a web application that works like a native app: installs on the home screen, works offline, sends push notifications.
  • Three mandatory components of PWA: HTTPS, Service Worker and manifest (manifest.json). Without any of these elements, the browser will not offer installation.
  • Service Worker — a background JavaScript script that intercepts network requests. It implements caching strategies: Cache First (static), Network First (API), Stale While Revalidate (content with updates).
  • Web App Manifest — a JSON file with display settings: name, icons, theme color, display (standalone, fullscreen, minimal-ui). Icons are required in 192x192 and 512x512 sizes.
  • Push Notifications in PWA work via Push API and Notification API. Service Worker receives the push event even when the app is closed.
  • Lighthouse checks PWA against a checklist. The minimum score for installation is 80 out of 100. Key metrics: FCP under 1.8 s, LCP under 2.5 s.
  • Workbox by Google simplifies Service Worker development: ready-made strategies, automatic caching, bundler integration.

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม