Установка PWA на устройства

Progressive Web App (PWA) представляет собой веб-приложение с возможностями нативного приложения: установка на устройство, работа офлайн, push-уведомления и высокая производительность. Для интеграции PWA с фронтенд-фреймворком Mithril требуется настроить манифест, сервис-воркеры и обработку событий установки.


Манифест приложения

Манифест (manifest.json) — это основной файл, описывающий PWA:

{
  "name": "Mithril PWA",
  "short_name": "MPWA",
  "start_url": "/index.html",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#1976d2",
  "icons": [
    {
      "src": "icons/icon-192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "icons/icon-512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}

Ключевые моменты манифеста:

  • start_url — адрес, с которого будет запускаться приложение при установке.
  • display: "standalone" — запуск приложения без элементов браузера.
  • theme_color и background_color влияют на оформление интерфейса и заставки.
  • icons — набор иконок разных размеров для разных устройств и экранов.

Манифест подключается через HTML:


Сервис-воркер

Сервис-воркер (service-worker.js) отвечает за кэширование и офлайн-доступ. Основная структура для Mithril-приложения:

const CACHE_NAME = 'mithril-pwa-cache-v1';
const URLS_TO_CACHE = [
  '/',
  '/index.html',
  '/app.js',
  '/styles.css'
];

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => cache.addAll(URLS_TO_CACHE))
      .then(() => self.skipWaiting())
  );
});

self.addEventListener('activate', event => {
  event.waitUntil(
    caches.keys().then(cacheNames =>
      Promise.all(
        cacheNames.map(name => {
          if (name !== CACHE_NAME) return caches.delete(name);
        })
      )
    )
  );
});

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(response => response || fetch(event.request))
  );
});

Важные моменты:

  • install — событие для кэширования необходимых ресурсов.
  • activate — удаление устаревших кэшей.
  • fetch — перехват запросов и предоставление кэшированного контента.

Регистрация сервис-воркера в Mithril:

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/service-worker.js')
    .then(reg => console.log('Service Worker зарегистрирован', reg))
    .catch(err => console.error('Ошибка регистрации', err));
}

Обработка установки PWA

Для отображения пользовательского приглашения на установку используется событие beforeinstallprompt. В Mithril можно создать компонент для управления этим процессом:

let deferredPrompt = null;

document.addEventListener('beforeinstallprompt', e => {
  e.preventDefault();
  deferredPrompt = e;
  m.redraw(); // Перерисовать интерфейс для отображения кнопки установки
});

const InstallButton = {
  view: () => deferredPrompt ? m('button', {
    onclick: () => {
      deferredPrompt.prompt();
      deferredPrompt.userChoice.then(choiceResult => {
        if (choiceResult.outcome === 'accepted') {
          console.log('Пользователь принял установку PWA');
        } else {
          console.log('Пользователь отклонил установку PWA');
        }
        deferredPrompt = null;
        m.redraw();
      });
    }
  }, 'Установить приложение') : null
};

Принципы работы:

  • Событие beforeinstallprompt предотвращает автоматическое отображение браузером баннера.
  • Сохраняется объект события deferredPrompt для вызова позже.
  • Пользователь нажимает кнопку, вызывается метод prompt(), и можно обработать результат через userChoice.

Особенности установки на мобильных устройствах

  • iOS: установка PWA через Safari доступна только через «Добавить на главный экран». Событие beforeinstallprompt не поддерживается. Необходимы метатеги:


  • Android: современные версии Chrome поддерживают стандартные события PWA. Можно показывать кастомную кнопку установки и отслеживать appinstalled:
window.addEventListener('appinstalled', () => {
  console.log('PWA успешно установлено на устройство');
});

Кэширование и обновление

Для корректного обновления PWA:

  1. Использовать версионирование кэшей (CACHE_NAME с номером версии).
  2. При activate удалять устаревшие кэши.
  3. При изменении ресурсов обновлять кэш через install или динамическое кэширование.

Пример динамического кэширования:

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(cached => {
      if (cached) return cached;
      return fetch(event.request).then(response => {
        return caches.open(CACHE_NAME).then(cache => {
          cache.put(event.request, response.clone());
          return response;
        });
      });
    })
  );
});

Интеграция с Mithril

Вся структура приложения строится на компонентах, поэтому PWA-функционал легко встраивается через:

  • Подключение сервис-воркера при инициализации приложения.
  • Создание отдельного компонента InstallButton для пользовательской установки.
  • Использование состояния и m.redraw() для управления отображением UI элементов PWA.

Mithril не требует дополнительного фреймворка для работы с PWA, так как сервис-воркеры и события установки работают на уровне браузера.