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));
}
Для отображения пользовательского приглашения на установку
используется событие 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.beforeinstallprompt не поддерживается. Необходимы
метатеги:
appinstalled:window.addEventListener('appinstalled', () => {
console.log('PWA успешно установлено на устройство');
});
Для корректного обновления PWA:
CACHE_NAME с
номером версии).activate удалять устаревшие кэши.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;
});
});
})
);
});
Вся структура приложения строится на компонентах, поэтому PWA-функционал легко встраивается через:
InstallButton для
пользовательской установки.m.redraw() для управления
отображением UI элементов PWA.Mithril не требует дополнительного фреймворка для работы с PWA, так как сервис-воркеры и события установки работают на уровне браузера.