Как создать PWA: полное руководство от основ до Service Workers
Перейти

Как создать PWA: полное руководство от основ до Service Workers

#Веб-разработка  #Основы JavaScript  #Web API  
Пройдите тест, узнайте какой профессии подходите
Сколько вам лет
0%
До 18
От 18 до 24
От 25 до 34
От 35 до 44
От 45 до 49
От 50 до 54
Больше 55

Для кого эта статья:

  • Фронтенд-разработчики и веб-разработчики всех уровней
  • Менеджеры проектов и владельцы бизнеса, заинтересованные в оптимизации приложений
  • Студенты и начинающие разработчики, изучающие современные веб-технологии

Когда я впервые запустил PWA-приложение на смартфоне клиента и оно продолжало работать в метро без интернета, его реакция была бесценна: "Это точно веб-сайт, а не нативное приложение?" 🚀 Прогрессивные веб-приложения изменили правила игры в мире веб-разработки, объединив лучшие качества веб-сайтов и нативных приложений в одно целое. Даже технологические гиганты вроде Twitter и Starbucks перешли на PWA, увеличив конверсию и снизив затраты на разработку. Независимо от вашего уровня – фронтендер с опытом или начинающий разработчик – это руководство проведет вас через все этапы создания полноценного PWA, от базового манифеста до продвинутых Service Workers.

Что такое PWA и почему они покоряют мир веб-разработки

Progressive Web Applications (PWA) представляют собой веб-приложения, которые используют современные веб-возможности для предоставления пользователям опыта, сравнимого с нативными приложениями. Они работают в браузере, но при этом могут быть установлены на домашний экран устройства, отправлять пуш-уведомления и функционировать офлайн. 💼

Андрей Соколов, технический директор

Когда наша компания столкнулась с дилеммой: разрабатывать нативные приложения для iOS и Android или искать альтернативное решение, бюджет был ограничен. Клиент — сеть ресторанов быстрого питания — требовал мобильное приложение с возможностью офлайн-просмотра меню и купонов. Разработка двух нативных приложений обошлась бы минимум в 2,5 млн рублей.

Мы предложили PWA-решение. Скептицизм клиента сменился восторгом, когда мы продемонстрировали прототип через три недели вместо обещанных шести для нативной разработки. Приложение работало офлайн, отправляло уведомления о специальных предложениях и загружалось за 2 секунды даже на бюджетных устройствах.

Результат превзошел ожидания: конверсия заказов выросла на 28%, а расходы на разработку сократились на 70% по сравнению с нативными приложениями. Сейчас, спустя полтора года, PWA остается основным каналом мобильных продаж компании.

Ключевые преимущества PWA перед традиционными веб-сайтами и нативными приложениями:

Характеристика Обычный веб-сайт PWA Нативное приложение
Установка на устройство Нет Да Да
Работа офлайн Нет Да Да
Доступ к API устройства Ограниченный Расширенный Полный
Пуш-уведомления Нет Да Да
Стоимость разработки Низкая Средняя Высокая
Обновление Мгновенное Мгновенное Через магазин приложений

Статистика внедрения PWA говорит сама за себя:

  • Twitter Lite (PWA) уменьшил использование данных на 70%, а время загрузки на 30%
  • Pinterest увеличил время, проведенное на сайте, на 40% после внедрения PWA
  • Alibaba увеличил конверсию новых пользователей на 104% с помощью своего PWA

Технологический стек PWA базируется на трех ключевых компонентах:

  1. Web App Manifest — JSON-файл, который содержит информацию о приложении (название, иконки, цвета и т.д.)
  2. Service Workers — JavaScript-файлы, работающие в фоновом режиме и обеспечивающие офлайн-функциональность, кеширование и пуш-уведомления
  3. Application Shell Architecture — подход к структурированию приложения, обеспечивающий мгновенную загрузку интерфейса
Пошаговый план для смены профессии

Основы создания PWA: манифест и архитектура приложения

Создание PWA начинается с разработки базовой структуры и Web App Manifest. Этот JSON-файл предоставляет браузеру информацию о вашем приложении и определяет, как оно будет отображаться при установке на устройство пользователя. 📱

Сначала создадим базовую структуру проекта:

/pwa-project
├── index.html
├── css/
│ └── styles.css
├── js/
│ ├── app.js
│ └── service-worker.js
├── images/
│ ├── icons/
│ └── content/
└── manifest.json

Теперь рассмотрим создание манифеста приложения. Вот пример базового manifest.json:

json
Скопировать код
{
"name": "Мое PWA Приложение",
"short_name": "PWA Демо",
"description": "Демонстрационное прогрессивное веб-приложение",
"start_url": "/index.html",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#2196f3",
"orientation": "portrait-primary",
"icons": [
{
"src": "/images/icons/icon-72x72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "/images/icons/icon-96x96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "/images/icons/icon-128x128.png",
"sizes": "128x128",
"type": "image/png"
},
{
"src": "/images/icons/icon-144x144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "/images/icons/icon-152x152.png",
"sizes": "152x152",
"type": "image/png"
},
{
"src": "/images/icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/images/icons/icon-384x384.png",
"sizes": "384x384",
"type": "image/png"
},
{
"src": "/images/icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}

Параметры манифеста и их значение:

Параметр Описание Влияние на UX
name Полное название приложения Отображается на экране загрузки
short_name Краткое название Показывается под иконкой на домашнем экране
start_url Начальная страница при запуске Определяет точку входа в приложение
display Режим отображения (standalone, fullscreen, minimal-ui, browser) Влияет на наличие элементов браузера в UI
background_color Цвет фона экрана загрузки Создает плавный визуальный переход при запуске
theme_color Основной цвет приложения Влияет на цвет строки состояния и интерфейса
icons Массив иконок разных размеров Обеспечивает корректное отображение на разных устройствах

Для подключения манифеста к HTML-документу добавьте следующую строку в <head> вашего index.html:

HTML
Скопировать код
<link rel="manifest" href="/manifest.json">

Также рекомендуется добавить мета-теги для улучшения интеграции с устройствами iOS, которые пока не полностью поддерживают веб-манифесты:

HTML
Скопировать код
<!-- iOS support -->
<link rel="apple-touch-icon" href="/images/icons/icon-192x192.png">
<meta name="apple-mobile-web-app-status-bar" content="#2196f3">

Архитектура PWA обычно следует модели Application Shell (оболочка приложения). Эта модель разделяет приложение на две основные части:

  1. Оболочка (Shell) — минимальный HTML, CSS и JavaScript, необходимый для работы пользовательского интерфейса
  2. Контент — динамические данные, которые загружаются при необходимости

Такой подход позволяет приложению быстро загружаться и работать даже при плохом соединении. Оболочка кешируется при первой загрузке и повторно используется при последующих посещениях, в то время как контент может обновляться асинхронно.

Реализация отзывчивого дизайна и быстродействия PWA

Отзывчивый дизайн и быстродействие — два столпа успешного PWA. Пользователи ожидают, что приложения будут работать плавно на любом устройстве и при любом качестве сети. Исследования показывают, что 53% мобильных пользователей покидают сайт, если он загружается более 3 секунд. Оптимизация этих параметров напрямую влияет на конверсию. 🚀

Для создания по-настоящему отзывчивого PWA следуйте этим принципам:

  • Используйте гибкие сетки с относительными единицами (%, em, rem)
  • Применяйте медиа-запросы для адаптации контента к разным экранам
  • Оптимизируйте изображения и используйте современные форматы (WebP, AVIF)
  • Внедряйте стратегию "Mobile First" при разработке стилей

Пример базовой структуры CSS для отзывчивого дизайна:

CSS
Скопировать код
/* Base styles (mobile first) */
.container {
width: 100%;
padding: 1rem;
}

/* Tablet styles */
@media (min-width: 768px) {
.container {
width: 750px;
margin: 0 auto;
}
}

/* Desktop styles */
@media (min-width: 1024px) {
.container {
width: 970px;
}
}

/* Large desktop styles */
@media (min-width: 1200px) {
.container {
width: 1170px;
}
}

Для оптимизации быстродействия PWA критически важно следовать этим практикам:

  1. Минимизация критического пути рендеринга

    • Размещайте критические CSS в теге <head>
    • Откладывайте загрузку некритических ресурсов
    • Используйте асинхронную загрузку скриптов (async/defer)
  2. Оптимизация изображений

    • Используйте правильные размеры и форматы
    • Применяйте ленивую загрузку (lazy loading)
    • Внедряйте тег <picture> для адаптивных изображений
  3. Эффективное кеширование

    • Настраивайте правильные HTTP-заголовки
    • Используйте хеши в именах файлов для версионирования
    • Применяйте стратегии кеширования Service Worker

Максим Ветров, ведущий frontend-разработчик

Работая над PWA для крупного интернет-магазина электроники, я столкнулся с проблемой: сайт загружался за 7-8 секунд на мобильных устройствах, показатель отказов достигал 65%, а конверсия падала.

Первым шагом стал аудит производительности через Lighthouse. Результаты были удручающими: 35 баллов из 100 по быстродействию. Основные проблемы: неоптимизированные изображения, блокирующие CSS/JS и отсутствие кеширования.

Я реализовал стратегию Application Shell — создал минимальный интерфейс, который кешировался при первом посещении, а затем загружался мгновенно. Для изображений внедрил ленивую загрузку и предзагрузку критических ресурсов через <link rel="preload">.

Радикальное улучшение принесла оптимизация CSS. Анализатор показал, что мы используем только 23% Bootstrap. Я вырезал все неиспользуемые стили, уменьшив CSS-файлы на 78%. Критические стили были внедрены в <head>, остальные подгружались асинхронно.

После всех оптимизаций время загрузки сократилось до 2,1 секунды, показатель отказов снизился до 38%, а конверсия выросла на 29%. Lighthouse теперь показывает 87 баллов по производительности. Но самый значимый результат — увеличение выручки магазина на 18% за первые три месяца после внедрения PWA.

Для оценки и улучшения производительности PWA используйте следующие метрики:

  • First Contentful Paint (FCP) — время до первого отображения контента
  • Largest Contentful Paint (LCP) — время отображения основного контента
  • First Input Delay (FID) — задержка первого взаимодействия пользователя
  • Cumulative Layout Shift (CLS) — суммарное смещение макета

Инструменты для измерения этих метрик:

  • Google Lighthouse — комплексный инструмент для анализа PWA
  • Chrome DevTools — панель Performance
  • PageSpeed Insights — онлайн-анализатор производительности
  • Web Vitals расширение для Chrome — для быстрых измерений

Service Workers: ключ к автономной работе приложения

Service Workers — это JavaScript-файлы, которые работают в фоновом режиме, отдельно от веб-страницы, предоставляя возможности, которые раньше были доступны только нативным приложениям. Они являются основой офлайн-функциональности PWA, позволяют реализовать кеширование ресурсов и поддерживать пуш-уведомления. 🛠️

Жизненный цикл Service Worker проходит через несколько фаз:

  1. Регистрация — сообщает браузеру о существовании Service Worker
  2. Установка — происходит, когда Service Worker загружается впервые или обновляется
  3. Активация — когда Service Worker становится действующим
  4. Ожидание — после установки, но перед активацией (если уже есть активный Service Worker)
  5. Завершение — когда Service Worker перестает быть активным

Начнем с базовой регистрации Service Worker. Добавьте следующий код в ваш основной JavaScript файл (например, app.js):

JS
Скопировать код
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/js/service-worker.js')
.then(function(registration) {
console.log('ServiceWorker успешно зарегистрирован со сферой действия: ', registration.scope);
})
.catch(function(error) {
console.log('Регистрация ServiceWorker провалена: ', error);
});
});
}

Теперь создадим базовый Service Worker (service-worker.js):

JS
Скопировать код
const CACHE_NAME = 'pwa-cache-v1';
const urlsToCache = [
'/',
'/index.html',
'/css/styles.css',
'/js/app.js',
'/images/icons/icon-192x192.png',
// Добавьте все ресурсы, которые хотите кешировать
];

// Установка Service Worker и кеширование ресурсов
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => {
console.log('Кеш открыт');
return cache.addAll(urlsToCache);
})
);
});

// Активация Service Worker и очистка устаревших кешей
self.addEventListener('activate', event => {
const cacheWhitelist = [CACHE_NAME];
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (cacheWhitelist.indexOf(cacheName) === -1) {
return caches.delete(cacheName);
}
})
);
})
);
});

// Перехват сетевых запросов
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => {
// Возврат кешированного ресурса, если он есть
if (response) {
return response;
}

// Клонирование запроса, так как он может быть использован только один раз
const fetchRequest = event.request.clone();

return fetch(fetchRequest).then(response => {
// Проверка валидности ответа
if (!response || response.status !== 200 || response.type !== 'basic') {
return response;
}

// Клонирование ответа, так как он может быть использован только один раз
const responseToCache = response.clone();

caches.open(CACHE_NAME)
.then(cache => {
cache.put(event.request, responseToCache);
});

return response;
});
})
);
});

Существует несколько стратегий кеширования, каждая из которых подходит для разных типов ресурсов:

Стратегия Описание Применение
Cache First Сначала проверяет кеш, затем сеть Статические ресурсы (CSS, JS, изображения)
Network First Сначала пытается получить из сети, потом из кеша Динамический контент, API-запросы
Stale While Revalidate Возвращает кешированный ответ, затем обновляет кеш Контент, который может обновляться, но не критично быстро
Cache Only Только из кеша, никогда из сети Офлайн-приложения, критические ресурсы оболочки
Network Only Только из сети, никогда из кеша Данные, которые всегда должны быть свежими

Пример реализации стратегии "Stale While Revalidate":

JS
Скопировать код
self.addEventListener('fetch', event => {
if (event.request.url.includes('/api/')) {
event.respondWith(
caches.open(CACHE_NAME).then(cache => {
return fetch(event.request).then(networkResponse => {
cache.put(event.request, networkResponse.clone());
return networkResponse;
}).catch(() => {
return cache.match(event.request);
});
})
);
} else {
// Для остальных ресурсов используем Cache First
event.respondWith(
caches.match(event.request)
.then(response => {
return response || fetch(event.request);
})
);
}
});

Для улучшения пользовательского опыта можно реализовать фоновую синхронизацию с помощью Service Worker:

JS
Скопировать код
// В вашем app.js
function saveDataLocally(data) {
// Сохранение данных в IndexedDB
// ...

// Запрос на фоновую синхронизацию
if ('serviceWorker' in navigator && 'SyncManager' in window) {
navigator.serviceWorker.ready.then(registration => {
return registration.sync.register('sync-data');
});
} else {
// Немедленная синхронизация, если API не поддерживается
sendDataToServer(data);
}
}

// В вашем service-worker.js
self.addEventListener('sync', event => {
if (event.tag === 'sync-data') {
event.waitUntil(
// Получение данных из IndexedDB и отправка на сервер
// ...
);
}
});

Для реализации пуш-уведомлений:

JS
Скопировать код
// В вашем app.js
function subscribeToPushNotifications() {
navigator.serviceWorker.ready.then(registration => {
return registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array('ваш_публичный_ключ')
});
}).then(subscription => {
// Отправьте подписку на ваш сервер
return fetch('/api/subscribe', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(subscription)
});
}).catch(error => {
console.error('Ошибка подписки на пуш-уведомления:', error);
});
}

// В вашем service-worker.js
self.addEventListener('push', event => {
const data = event.data.json();

const options = {
body: data.body,
icon: '/images/icons/icon-192x192.png',
badge: '/images/icons/badge-72x72.png',
vibrate: [100, 50, 100],
data: {
url: data.url
}
};

event.waitUntil(
self.registration.showNotification(data.title, options)
);
});

self.addEventListener('notificationclick', event => {
event.notification.close();

event.waitUntil(
clients.openWindow(event.notification.data.url)
);
});

Развёртывание и тестирование PWA для разных устройств

После создания PWA необходимо тщательно протестировать и правильно развернуть приложение. Развертывание и тестирование PWA отличается от обычных веб-приложений, поскольку необходимо учитывать особенности работы в офлайн-режиме, установку на устройства и взаимодействие с различными платформами. 📱💻

Перед развертыванием убедитесь, что ваше PWA соответствует следующим критериям:

  • Работает по HTTPS (обязательно для Service Worker)
  • Имеет корректный Web App Manifest
  • Реализует адаптивный дизайн для всех размеров экрана
  • Функционирует в офлайн-режиме
  • Загружается быстро даже на медленных соединениях

Чек-лист для развертывания PWA:

  1. Настройка HTTPS

    • Получите SSL-сертификат (Let's Encrypt предоставляет бесплатные сертификаты)
    • Настройте перенаправление с HTTP на HTTPS
    • Проверьте наличие mixed content (смешанного контента)
  2. Оптимизация для поисковых систем

    • Добавьте мета-теги для правильной индексации
    • Реализуйте микроданные schema.org
    • Создайте карту сайта (sitemap.xml)
  3. Настройка серверной части

    • Установите правильные HTTP-заголовки кеширования
    • Настройте сжатие ресурсов (Gzip, Brotli)
    • Реализуйте серверную логику для пуш-уведомлений

Инструменты для тестирования PWA:

  • Lighthouse — встроенный в Chrome DevTools инструмент для комплексной оценки PWA
  • Chrome DevTools — вкладка Application для тестирования Service Worker, манифеста и хранилища
  • PWA Builder — проверяет соответствие требованиям PWA и помогает генерировать необходимые файлы
  • BrowserStack — для тестирования на разных устройствах и платформах
  • Puppeteer — для автоматизированного тестирования

При тестировании обратите внимание на следующие аспекты PWA:

Аспект Что проверять Инструменты
Установка Появление баннера установки, процесс установки на разных платформах Chrome для Android, Safari для iOS
Офлайн-работа Поведение при отключении интернета, доступ к кешированному контенту DevTools (Network tab → Offline)
Производительность Время загрузки, отзывчивость интерфейса, потребление ресурсов Lighthouse, WebPageTest
Доступность Контрастность, навигация с клавиатуры, совместимость со скринридерами Axe DevTools, Chrome Accessibility Audit
Совместимость Работа на различных устройствах, браузерах и операционных системах BrowserStack, CrossBrowserTesting

Несколько практических советов по тестированию PWA:

  1. Тестируйте на реальных устройствах, а не только в эмуляторах. Особенно важно проверить работу на iOS, где поддержка PWA имеет ограничения.
  2. Симулируйте различные сетевые условия (3G, 4G, офлайн) для проверки стратегий кеширования.
  3. Проверьте процесс обновления PWA — что происходит, когда вы обновляете Service Worker или манифест.
  4. Тестируйте различные сценарии использования, включая переходы между онлайн и офлайн режимами.
  5. Убедитесь, что пользовательские данные корректно сохраняются между сессиями (IndexedDB, localStorage).

После успешного тестирования и развертывания не забудьте о мониторинге и аналитике:

  • Настройте отслеживание установок PWA через Google Analytics
  • Мониторьте производительность с помощью Real User Monitoring (RUM)
  • Отслеживайте ошибки Service Worker через систему логирования
  • Собирайте отзывы пользователей о работе приложения

Популярные хостинг-платформы для PWA:

  • Firebase Hosting — интегрируется с другими сервисами Firebase
  • Netlify — автоматизирует деплой из Git-репозитория
  • Vercel — оптимизирован для фронтенд-фреймворков
  • GitHub Pages — бесплатный хостинг для статических сайтов
  • AWS Amplify — полный стек для веб и мобильных приложений

PWA — это не просто модный термин, а технология, которая стирает границы между веб и нативными приложениями, предоставляя пользователям лучший опыт независимо от устройства или качества соединения. Следуя шагам из этого руководства, вы создадите приложение, которое загружается молниеносно, работает офлайн и выглядит как нативное. Начните с малого — внедрите базовый манифест и простой Service Worker, постепенно расширяя функциональность. Помните: каждая оптимизация имеет значение. Даже простое PWA может значительно повысить вовлеченность пользователей и конверсию по сравнению с обычным сайтом. Действуйте — будущее веба уже здесь.

Проверь как ты усвоил материалы статьи
Пройди тест и узнай насколько ты лучше других читателей
Что такое Progressive Web Apps (PWA)?
1 / 5

Станислав Плотников

фронтенд-разработчик

Свежие материалы

Загрузка...