Дата публикации:

Любой сайт, независимо от исходной платформы, потенциально может стать PWA. PWA строится на HTML, CSS и JavaScript, поэтому для преобразования сайта достаточно выполнить несколько требований.

Web manifest

Минимальный manifest содержит описание, цвета, иконки и адреса:

{
  "background_color": "#000000",
  "description": "Simple PWA",
  "display": "standalone",
  "icons": [
    {"sizes": "180x180", "src": "./img/favicon-180.png", "type": "image/png"},
    {"sizes": "192x192", "src": "./img/favicon-192.png", "type": "image/png"},
    {"sizes": "512x512", "src": "./img/favicon-512.png", "type": "image/png"}
  ],
  "id": "/", "name": "Simple PWA", "scope": "./",
  "short_name": "Simple PWA", "start_url": "./", "theme_color": "#000000"
}

Иконка

Иконки представляют приложение на домашнем экране, панели задач и в переключателе приложений. Нужны разные размеры, включая 192x192 и 512x512 для Android и 180x180 для Apple; используйте PNG или SVG.

Service Worker

Чтобы приложение можно было установить на телефон, service worker должен хотя бы обеспечить offline-доступ к app shell. Остальные ресурсы кэшировать необязательно:

'use strict';
const CACHE_STATIC = 'static-cache-v1';
const FILES_TO_CACHE = ['./', './favicon.ico', './img/favicon-512.png', './index.html', './pwa.json'];

function onActivate(evt) {
  evt.waitUntil(self.clients.claim());
}
function onFetch(evt) {
  async function cacheOrFetch(req) {
    const cache = await self.caches.open(CACHE_STATIC);
    const cached = await cache.match(req);
    return cached ?? await fetch(req);
  }
  evt.respondWith(cacheOrFetch(evt.request));
}
function onInstall(evt) {
  async function cacheStaticFiles() {
    const cache = await caches.open(CACHE_STATIC);
    await Promise.all(FILES_TO_CACHE.map((url) => cache.add(url).catch((reason) => {
      console.log(`'${url}' failed: ${String(reason)}`);
    })));
  }
  evt.waitUntil(cacheStaticFiles());
}
self.addEventListener('activate', onActivate);
self.addEventListener('fetch', onFetch);
self.addEventListener('install', onInstall);

App Shell

App shell — главный файл сайта, обычно index.html. Он указывает браузеру manifest и регистрирует service worker:

<link rel="manifest" href="./pwa.json">
<script>
if ('serviceWorker' in navigator) {
  self.addEventListener('load', async () => {
    const container = navigator.serviceWorker;
    if (container.controller === null) await container.register('sw.js');
  });
}
</script>

Заключение

Почти любой сайт можно превратить в PWA по этим правилам. Но минимальная PWA лишь помещает иконку сайта на домашний экран. Чтобы использовать современные Web API по-настоящему, приложение с самого начала должно учитывать offline-работу, хранение данных на клиенте и вычисления в браузере.