Любой сайт, независимо от исходной платформы, потенциально может стать PWA. PWA строится на HTML, CSS и JavaScript, поэтому для преобразования сайта достаточно выполнить несколько требований.
- HTTPS: сайт должен работать по HTTPS.
- Web manifest: браузер получает метаданные PWA.
- Иконка: нужна для размещения приложения на домашнем экране смартфона.
- Service Worker: JavaScript обрабатывает запросы и может ответить при offline-работе.
- App Shell: HTML-код устанавливает и запускает PWA.
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-работу, хранение данных на клиенте и вычисления в браузере.