РАЗРАБОТКА PWA (Progressive Web Applications)
PWA (Progressive Web Applications) - веб-сайт с возможностью установки на устройство пользователя и использования в виде нативного приложения в дальнейшем.
На самом деле общего и точного определения у PWA нет, но для обычного пользователя все сводится к двум показателям: возможность установить PWA на мобильное устройство и использование веб-ресурса offline. Основная задача PWA - позволить работать с веб-сайтом как с “нативным” приложением на любом устройстве.
PWA-технология предоставляет отдельный слой логики для веб-сайта, которая по своей сути является “оберткой”. Данная особенность означает, что мы не ограничены в выборе инструментов для разработки приложения. Однако, есть базовые ограничения для использования всех возможностей PWA-технологии:
- Браузеры Chrome или Safari.
На данный момент PWA-технология полностью поддерживается браузерами Chrome и Safari. Начиная с версии 16.4 Safari стал поддерживать push-уведомления. - HTTPS-протокол ресурса PWA.
Для полноценной работы как PWA-технологии, так и большинства браузерных API требуется HTTPS-протокол. При запуске на HTTP у приложения не будет возможности установки и использования ServiceWorker. - Зарегистрированный ServiceWorker (SW) и файл manifest.json.
То, что делает наш сайт именно PWA-приложением:
- SW является событийно-управляемым “воркером”, который работает в потоке отдельном от основного потока JavaScript на странице, обеспечивает установку приложения на устройство, работу приложения в оффлайн, стратегии кэширования и многое другое.
- Файл manifest.json содержит в себе настройки для предоставления нативных функций PWA-приложению.
Жизненный цикл ServiceWorker
- Регистрация SW. Проверяем наличие API ServiceWorker в браузере и вызываем метод регистрации в точке входа в приложение (/public/index.html) или корневом файле (/src/index.jsx).
- Событие Install. Срабатывает сразу после регистрации. При обработке события доступно взаимодействие с кэшем ServiceWorker и отслеживание события update - наличия новых обновлений приложения.
- Событие Activate. ServiceWorker установлен, при обработке события можно удалить старый кэш.
- Режим idle. После установки ServiceWorker переходит в “спящий режим” до момента следующего вызова.
- Событие fetch. Срабатывает при каждом API-запросе. Для кэширования ответов и использования данных offline необходимо указание настроек для стратегии кэширования в приложении.
Стратегии кэширования данных для ServiceWorker
- “Cache first”.
- Суть: API-запрос направляется в кэш, при отсутствии ответа - в сеть.
- Применение: подходит для ресурсов, которые редко изменяются (лого, шрифты).
- “Network first”.
- Суть: сначала делается API-запрос к сети, если сеть недоступна - проверяется кэш.
- Применение: подходит для часто меняющегося контента (данные пользователя).
- “Cashe only”.
- Суть: все API-запросы направляются в кэш, если ресурса нет, то он не будет загружен.
- Применение: подходит для приложений со статикой (landing).
- “Network only”.
- Суть: все API-запросы направляются в сеть, кэш игнорируется.
- Применение: подходит для данных, которые всегда должны быть актуальными (банковские данные).
- “Stale-While-Revalidate”.
- Суть: сначала проверяется кэш и возвращается кэшированный ресурс (если доступен), одновременно отправляется API-запрос для обновления кэша.
- Применение: подходит для загрузки и обновления изображений.
Разработка приложения
При старте нового проекта лучше всего использовать готовые шаблоны (Vite - vite-pwa-plugin, Webpack - cra-template-pwa и т.д.), которые серьезно облегчат взаимодействие с SW и его настройку.
Наиболее распространенной стратегией кэширования является Network first, которая по своей сути и отражает основное назначение SW: предоставить возможность пользователю взаимодействовать с приложением оффлайн при отсутствии доступа к сети. При отсутствии настроек по стратегии кэширования в приложении базовые ресурсы (JavaScript, CSS, HTML) будут предварительно кэшироваться во время установки SW, пользователь сможет использовать приложение offline, но только с теми архивными ресурсами, которые были предварительно кэшированы.
Процесс разработки
Вариант для Vite + vite-pwa-plugin + ReactJS
- Создаем новое приложение по шаблону от Vite при помощи команды:
npm create vite@latest
- Разрабатываем MVP-версию приложения приложения на ReactJS.
Процесс разработки самих интерфейсов PWA-приложения ничем не отличается от разработки обычного веб-сайта, но зачастую требует наличия адаптивной верстки и дизайна для мобильных устройств. - Устанавливаем плагин для генерации PWA-assets при помощи команды:
npm i @vite-pwa/assets-generator -D
Настраиваем конфигурацию плагина vite-pwa-plugin в файле vite.config.js либо vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { VitePWA } from "vite-plugin-pwa";
export default defineConfig({
plugins: [
react(),
VitePWA({
injectRegister: 'auto',
registerType: 'autoUpdate',
includeAssets: ["favicon.ico", "apple-touch-icon.png", "mask-icon.svg"],
manifest: {
name: "My Awesome App",
short_name: "MyApp",
description: "My Awesome App description",
theme_color: "#ffffff",
icons: [
{
src: "pwa-192x192.png",
sizes: "192x192",
type: "image/png",
},
{
src: "pwa-512x512.png",
sizes: "512x512",
type: "image/png",
},
],
},
}),
],
});
- Указываем настройки для стратегии кэширования в приложении по стратегии Network first:
export default defineConfig({
plugins: [
react(),
VitePWA({
...other settings,
workbox: {
runtimeCaching: [
{
urlPattern: /^https:\/\/test-api-domain\.com\/.*$/,
handler: 'NetworkFirst',
options: {
cacheName: 'api-cache',
networkTimeoutSeconds: 10,
expiration: {
maxEntries: 50,
maxAgeSeconds: 5 * 60,
},
}
},
],
}
}),
],
});
- urlPattern - регулярное выражение для определения шаблона URL, для которого будет применена стратегия кэширования. В данном примере это любые API-запросы, содержащие в адресе строку “https://test-api-domain.com/”.
- handler - задает стратегию кэширования. В данном случае 'NetworkFirst'.
- options.cacheName - имя кэша, который будет использоваться для хранения ответов.
- options.networkTimeoutSeconds - таймаут для сетевого запроса в секундах.
- options.expiration.maxEntries - максимальное количество записей, которые можно сохранить в кэше.
- options.expiration.maxAgeSeconds - максимальное время хранения в секундах для записей.
- Добавляем новый скрипт в package.json для создания PWA-assets (ссылка на источник): "generate-pwa-assets": "pwa-assets-generator --preset minimal public/logo.svg"
- Добавляем исходный svg-файл с логотипом приложения (public/logo.svg) и запускаем скрипт для создания PWA-assets: npm run generate-pwa-assets
Указываем код в index.html для использования PWA-assets (ссылка на источник):
<head>
...other code
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>My Awesome App</title>
<meta name="description" content="My Awesome App description">
<link rel="icon" href="/favicon.ico">
<link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180">
<link rel="mask-icon" href="/mask-icon.svg" color="#FFFFFF">
<meta name="theme-color" content="#ffffff">
</head>
- Запускаем команды в консоли:
npm run build
npm run preview
- Проверяем приложение:
- Браузер → инструменты разработчика → Application → Service Workers → на вкладке должна быть указана информация о SW приложения.
- В крайнем правом углу должна появиться кнопка с возможностью установить приложение на устройство.
- Тестирование стратегии кэширования:
- Взаимодействуем с приложением для отправки нескольких API-запросов по адресу, указанному в настройках стартегии кэширования.
- Ответы успешных запросов будут сохранены в кэш SW.
- В инструментах разработчика отключаем сеть.
- Переходим на страницы, с которых отправлялись запросы: данные должны быть отображены в режиме offline.
Данный вариант позволяет быстро развернуть стандартное PWA-приложение, а также преобразовать в PWA-приложение уже существующий веб-ресурс при условии, что изначально использовался сборщик Vite.
Нет времени на разработку?
Конвертация PWA-приложения в APK файл
ОС Android
Для данной ОС возможна конвертация PWA-приложения в apk файл, с его последующей установкой на устройстве:
- Онлайн-сервис PWA Builder (ссылка на онлайн-сервис PWA Builder )
- Переходим на сайт
- указываем веб-адрес PWA-приложения, жмем Start
- по результатам сканирования могут быть выявлены критические недостатки, которые не позволяют сервису собрать сборку
- устраняем недостатки, деплоим, повторяем предыдущие действия
- если сканирование успешно, в верхнем правом углу будет активна кнопка Package for stores → жмем, выбираем Generate package на карточке Android
- будет загружен архив, из архива нам нужен сам .apk-файл
- загружаем файл на Android-устройство и устанавливаем
- Локально при помощи Bubblewrap + Gruddle + Java Development Kit
- выполняем команду в консоли:
npm install -g @bubblewrap/cli
- переходим в директорию PWA-приложения, выполняем команду:
bubblewrap init --manifest https://test.pwa/manifest.json
(адрес заменить на URL-адрес Web App Manifest файла) - в ходе инициализации скачиваем недостающие пакеты, указываем требуемые настройки.
- выполняем в консоли команду:
bubblewrap build
- проверяем наличие .apk-файла в нашем проекте
Также читайте:
- Как хранить несколько билдов на одном домене и как управлять версиями PWA приложения
- Единое решение для ssh-аутентификации