Реалізація PWA (Progressive Web App) для сайту

Ваш сайт втрачає відвідувачів через повільне завантаження та відсутність офлайн-доступу? Ми розробляємо PWA, яке поєднує швидкість вебу та можливості нативних застосунків. Наша команда реалізує проєкт під ключ — від налаштування Service Worker до встановлення на домашній екран, забезпечуючи стабільну роботу та подальшу підтримку.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 2062 послуг
Реалізація PWA (Progressive Web App) для сайту
Складний
від 1 тижня до 3 місяців
Часті запитання

Розробка Progressive Web App (PWA)

Сайт втрачає до 40% трафіку, якщо користувач іде через повільне завантаження? Або кожен другий відвідувач не повертається після першого візиту? Ми допомагаємо впровадити PWA під ключ — це рішення, яке поєднує швидкість вебу та можливості нативних застосунків. PWA встановлюється на домашній екран, працює офлайн і може надсилати push-сповіщення. За 2–4 дні ви отримуєте застосунок, який завантажується в 2 рази швидше на повільних з'єднаннях. За даними Google, PWA збільшують конверсію на 36% і знижують відмови на 15%. Середня вартість залучення клієнта (CAC) при цьому суттєво знижується, що економить бюджет на рекламу.

Як PWA вирішує проблему офлайн-доступу?

Основний біль: користувач втрачає зв'язок — сайт недоступний. Service Worker кешує ключові ресурси (App Shell) та сторінки. Навіть при обриві з'єднання людина бачить інтерфейс, а не помилку. Ми використовуємо три стратегії кешування залежно від типу даних:

Стратегія Застосування Поведінка
Cache First Статика (CSS, JS, зображення) Віддає з кешу, оновлює фоном
Network First HTML-сторінки Спочатку мережа, при помилці — кеш
Stale While Revalidate Зображення, API Миттєво з кешу, потім оновлює

Web App Manifest — основа встановлюваності

Для появи кнопки «Додати на головний екран» потрібен коректний маніфест. Ми налаштовуємо всі поля: name, short_name, icons у 8 розмірах (включаючи maskable), screenshots для Android, shortcuts для швидких дій. Приклад маніфесту:

{
  "name": "ТехноМагазин — купити електроніку",
  "short_name": "ТехноМагазин",
  "description": "Смартфони, ноутбуки, аксесуари з доставкою",
  "start_url": "/?source=pwa",
  "scope": "/",
  "display": "standalone",
  "orientation": "portrait-primary",
  "theme_color": "#1a73e8",
  "background_color": "#ffffff",
  "lang": "uk",
  "dir": "ltr",
  "icons": [
    {
      "src": "/icons/icon-72.png",
      "sizes": "72x72",
      "type": "image/png"
    },
    {
      "src": "/icons/icon-96.png",
      "sizes": "96x96",
      "type": "image/png"
    },
    {
      "src": "/icons/icon-128.png",
      "sizes": "128x128",
      "type": "image/png"
    },
    {
      "src": "/icons/icon-144.png",
      "sizes": "144x144",
      "type": "image/png"
    },
    {
      "src": "/icons/icon-152.png",
      "sizes": "152x152",
      "type": "image/png"
    },
    {
      "src": "/icons/icon-192.png",
      "sizes": "192x192",
      "type": "image/png",
      "purpose": "any maskable"
    },
    {
      "src": "/icons/icon-384.png",
      "sizes": "384x384",
      "type": "image/png"
    },
    {
      "src": "/icons/icon-512.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "any maskable"
    }
  ],
  "screenshots": [
    {
      "src": "/screenshots/mobile-catalog.webp",
      "sizes": "390x844",
      "type": "image/webp",
      "form_factor": "narrow",
      "label": "Каталог товарів"
    }
  ],
  "shortcuts": [
    {
      "name": "Кошик",
      "url": "/cart",
      "icons": [
        {
          "src": "/icons/cart-96.png",
          "sizes": "96x96"
        }
      ]
    },
    {
      "name": "Обране",
      "url": "/wishlist",
      "icons": [
        {
          "src": "/icons/heart-96.png",
          "sizes": "96x96"
        }
      ]
    }
  ],
  "share_target": {
    "action": "/share",
    "method": "POST",
    "enctype": "multipart/form-data",
    "params": {
      "title": "title",
      "text": "text",
      "url": "url"
    }
  }
}
<link rel="manifest" href="/manifest.json">
<meta name="theme-color" content="#1a73e8">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<meta name="apple-mobile-web-app-title" content="ТехноМагазин">
<link rel="apple-touch-icon" href="/icons/icon-192.png">

Додатково: рекомендуємо прочитати документацію Web App Manifest для глибокого розуміння.

Чому Service Worker — основа PWA?

Service Worker — це проксі між браузером і мережею. Він перехоплює запити та вирішує, чи віддавати кеш, надсилати запит або показувати офлайн-сторінку. Без нього PWA не існує. Ми реалізуємо стратегію «Cache First для статики, Network First для HTML, Stale While Revalidate для медіа». Приклад базового Service Worker:

// sw.js — базова стратегія для PWA
const CACHE_VERSION = 'v3';
const APP_SHELL = [
  '/',
  '/manifest.json',
  '/offline.html',
  '/css/app.css',
  '/js/app.js',
  '/fonts/inter-regular.woff2',
  '/icons/icon-192.png',
];

// Встановлення: кешуємо App Shell
self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(`shell-${CACHE_VERSION}`)
      .then(cache => cache.addAll(APP_SHELL))
      .then(() => self.skipWaiting())
  );
});

// Активація: видаляємо старі кеші
self.addEventListener('activate', event => {
  event.waitUntil(
    caches.keys()
      .then(keys => Promise.all(
        keys.filter(k => !k.endsWith(CACHE_VERSION))
          .map(k => caches.delete(k))
      ))
      .then(() => self.clients.claim())
  );
});

// Fetch: різні стратегії для різних ресурсів
self.addEventListener('fetch', event => {
  const { request } = event;
  const url = new URL(request.url);

  // App Shell — cache first
  if (APP_SHELL.includes(url.pathname)) {
    event.respondWith(
      caches.match(request).then(r => r || fetch(request))
    );
    return;
  }

  // HTML-сторінки — network first, fallback offline
  if (request.headers.get('Accept')?.includes('text/html')) {
    event.respondWith(
      fetch(request)
        .then(response => {
          const clone = response.clone();
          caches.open(`pages-${CACHE_VERSION}`)
            .then(cache => cache.put(request, clone));
          return response;
        })
        .catch(() => caches.match(request)
          .then(cached => cached || caches.match('/offline.html'))
        )
    );
    return;
  }

  // Зображення — stale while revalidate
  if (request.destination === 'image') {
    event.respondWith(
      caches.open(`images-${CACHE_VERSION}`).then(async cache => {
        const cached = await cache.match(request);
        const fetchPromise = fetch(request).then(response => {
          cache.put(request, response.clone());
          return response;
        });
        return cached ?? fetchPromise;
      })
    );
  }
});

Детальніше про Service Worker читайте в довіднику MDN.

Як додати кнопку встановлення на сайт?

Щоб користувач міг встановити PWA, потрібно обробити подію beforeinstallprompt. Ми реалізуємо React-хук useInstallPrompt:

// useInstallPrompt.ts
export function useInstallPrompt() {
  const [installPrompt, setInstallPrompt] = useState<BeforeInstallPromptEvent | null>(null);
  const [isInstalled, setIsInstalled] = useState(false);

  useEffect(() => {
    const handler = (e: BeforeInstallPromptEvent) => {
      e.preventDefault();
      setInstallPrompt(e);
    };

    window.addEventListener('beforeinstallprompt', handler as EventListener);
    window.addEventListener('appinstalled', () => setIsInstalled(true));

    // Перевірити — чи вже встановлено?
    if (window.matchMedia('(display-mode: standalone)').matches) {
      setIsInstalled(true);
    }

    return () => window.removeEventListener('beforeinstallprompt', handler as EventListener);
  }, []);

  const install = async () => {
    if (!installPrompt) return;
    const result = await installPrompt.prompt();
    if (result.outcome === 'accepted') {
      setIsInstalled(true);
      setInstallPrompt(null);
    }
  };

  return { canInstall: !!installPrompt && !isInstalled, install, isInstalled };
}

// Використання в компоненті
function InstallBanner() {
  const { canInstall, install } = useInstallPrompt();
  if (!canInstall) return null;
  return (
    <div className="install-banner">
      <p>Встановіть застосунок для швидкого доступу</p>
      <button onClick={install}>Встановити</button>
    </div>
  );
}

Приклад offline-сторінки

<!-- /offline.html -->
<!DOCTYPE html>
<html lang="uk">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Немає з'єднання — ТехноМагазин</title>
  <style>
    body {
      font-family: system-ui;
      display: flex;
      align-items: center;
      justify-content: center;
      height: 100vh;
      margin: 0;
    }
    .offline {
      text-align: center;
    }
  </style>
</head>
<body>
  <div class="offline">
    <svg><!-- іконка wifi off --></svg>
    <h1>Немає з'єднання</h1>
    <p>Перевірте підключення до інтернету та оновіть сторінку</p>
    <button onclick="location.reload()">Спробувати знову</button>
  </div>
</body>
</html>

Чому PWA не встановлюється: типові помилки

Навіть при коректному маніфесті та Service Worker встановлення може не спрацювати. Часта причина — відсутність HTTPS або неправильні іконки. На iOS потрібно явно вказати apple-mobile-web-app-capable і додати іконки потрібних розмірів. Ще одна проблема: браузер відхиляє встановлення, якщо сайт не відповідає критеріям якості (Lighthouse PWA audit). Ми перевіряємо всі ці моменти: тестуємо на Chrome, Safari, Firefox, Android та iOS. Якщо push-сповіщення не працюють, швидше за все, не налаштовано VAPID-ключ або сертифікат. Всі ці нюанси ми відпрацьовуємо на етапі тестування.

Що входить в роботу

  • Web App Manifest — повна конфігурація з іконками, сплешами, шорткатами.
  • Service Worker — реєстрація, стратегії кешування, оновлення версій.
  • Offline-сторінка — адаптивна, з кнопкою перезавантаження.
  • Install Prompt — кнопка встановлення на десктоп та мобільні.
  • Push-сповіщення — опціонально, інтеграція з Firebase або стороннім сервісом.
  • Аудит Lighthouse — гарантуємо зелені перевірки PWA розділу.
  • Документація — опис архітектури кешування та інструкція з оновлення.

Строки розробки

Етап Час
Маніфест і мета-теги 0.5 дня
Service Worker + стратегії 1–1.5 дня
Offline-сторінка 0.5 дня
Install Prompt і тестування 0.5 дня
Push-сповіщення (опціонально) +1–2 дні

Підсумковий термін: від 2 до 4 днів без push, до 6 днів з ними. Вартість розраховується індивідуально — пишіть, оцінимо ваш проект.

Як ми працюємо

  1. Аналітика — вивчаємо структуру сайту, визначаємо App Shell.
  2. Проектування — обираємо стратегії кешування під ваш контент.
  3. Реалізація — пишемо Service Worker, налаштовуємо маніфест, інтегруємо хуки.
  4. Тестування — перевіряємо на Chrome, Safari, Firefox, Android та iOS.
  5. Деплой — завантажуємо на продакшен, моніторимо через Lighthouse.

Наша команда має 5+ років досвіду в PWA. За цей час реалізували проекти для інтернет-магазинів, медіа та SaaS. Гарантуємо підтримку актуальних стандартів і сумісність з останніми версіями браузерів. Зв'яжіться з нами, щоб отримати консультацію — розповімо, як PWA покращить ваш бізнес. Замовте впровадження PWA вже сьогодні.

Наші компетенції:

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1394
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1369
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1142
  • Розробка веб-сайту для компанії ФІКСПЕР
    Розробка веб-сайту для компанії ФІКСПЕР
    1060