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

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.

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

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

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

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

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

Етапи розробки

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

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1359
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1251
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    957
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1188
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    929
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Розробка веб-сайту для компанії ФІКСПЕР
    947

Розробка 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 вже сьогодні.

Коли додаток не відкривається без інтернету, користувач іде до конкурентів

PWA перетворює сайт на надійний додаток, який працює навіть в офлайні, надсилає push-повідомлення та встановлюється на головний екран. Розробка PWA додатків — це впровадження Service Worker, налаштування кеш-стратегій та інтеграція Web Push. На відміну від нативних додатків, вам не потрібні дві команди під iOS та Android — один код працює у всіх сучасних браузерах. Замовте аудит вашого проекту на PWA-сумісність — ми безкоштовно оцінимо потенціал та терміни.

Як Service Worker керує мережевими запитами?

Service Worker — це JavaScript-проксі між браузером та мережею. Працює в окремому потоці, перехоплює запити та вирішує, звідки їх віддавати: з кешу, з мережі або комбінацією. Розглянемо три базові стратегії на реальних сценаріях.

Стратегія кешування Використання Поведінка при офлайн
Cache First статика (CSS/JS з content hash) віддається з кешу, миттєво
Network First API, замовлення, новини спочатку мережа, при помилці — кеш
Stale While Revalidate контент соцмереж, стрічка сторінок одразу кеш, потім оновлення

Cache First застосовується для активів з хешем в імені — файл ніколи не зміниться, можна кешувати назавжди. Stale While Revalidate оптимальна для контенту, де допустима невелика затримка актуалізації. Workbox від Google автоматизує версіонування кешу та інвалідацію — без нього коректний Service Worker вимагатиме 300+ рядків коду з нетривіальними edge cases. Vite + vite-plugin-pwa генерує Service Worker з конфігу, включаючи precaching статики.

import { VitePWA } from 'vite-plugin-pwa';
export default {
  plugins: [
    VitePWA({
      registerType: 'autoUpdate',
      includeAssets: ['favicon.ico'],
      manifest: { /* name, icons, start_url, display */ },
      workbox: {
        globPatterns: ['**/*.{js,css,html,ico,png,svg}'],
        runtimeCaching: [
          { urlPattern: /^https?:\/\/api\./,
            handler: 'NetworkFirst',
            options: { cacheName: 'api-cache' }
          }
        ]
      }
    })
  ]
};

Як офлайн-режим реалізується на практиці?

«Працює офлайн» для різних продуктів означає різне. Ось три типові сценарії.

  • Офлайн-читання (новинні сайти, документація): Service Worker кешує сторінки при першому візиті, стратегія Stale While Revalidate + Background Sync для синхронізації після відновлення з'єднання.
  • Офлайн-редагування (нотатки, завдання): IndexedDB зберігає локальні дані, Background Sync API ставить операції в чергу — браузер синхронізує сам, навіть якщо вкладка закрита. Обмеження: Background Sync підтримується тільки в Chromium.
  • Офлайн-форма: користувач натиснув «Надіслати» без інтернету — дані не втрачаються, а ставляться в чергу та надсилаються автоматично. Для медичних та страхових форм це критично.

Проблема, про яку часто забувають: конфлікти при синхронізації. Якщо користувач А редагував запис офлайн, а користувач Б змінив його онлайн — потрібна стратегія вирішення (last-write-wins, three-way merge або показ конфлікту користувачеві). Ми опрацьовуємо ці сценарії на етапі проектування.

Як працюють Web Push-повідомлення?

Web Push доставляє повідомлення через браузер + Push Service (FCM для Chrome/Edge, APNs для Safari). Користувач надає дозвіл → браузер підписується на Push Service → ви отримуєте endpoint та ключі → надсилаєте повідомлення → Push Service доставляє в браузер. Реалізація через бібліотеку web-push (Node.js) або аналог для вашого бекенду. VAPID-ключі генеруються один раз, підписка зберігається в базі даних.

На поточний момент iOS (починаючи з версії 16.4) підтримує Web Push тільки для встановлених PWA, Chrome/Firefox/Edge — повна підтримка без встановлення. Частота та релевантність повідомлень безпосередньо впливають на відтік підписників — A/B тестування часу надсилання та формулювань стандартна практика.

Чому варто обрати PWA замість нативних додатків?

Економія на розробці під дві платформи — до 60% бюджету. Один код, єдина бізнес-логіка, автоматичне оновлення без магазинів. Ми виконали понад 30 PWA-проектів для e-commerce, фінтеху та корпоративних систем — гарантуємо сумісність з останніми версіями браузерів та відмінні показники Core Web Vitals (LCP, CLS, INP). PWA збільшує конверсію в середньому на 36% (дані Google). Сертифіковані спеціалісти з досвідом 7+ років у веб-розробці.

Що входить у розробку PWA під ключ?

Етап Результат Термін
Аудит поточного додатку Звіт PWA‑score, рекомендації 1–2 дні
Проектування офлайн‑сценаріїв Документація, прототип 2–3 дні
Розробка Service Worker + маніфест Код, автоматичне тестування 5–10 днів
Інтеграція Web Push (опціонально) Бекенд‑ендпоінт, підписка 3–5 днів
Тестування на реальних пристроях Звіт, правки 3–5 днів
Деплой та документація Доступи, інструкція, гарантія 1 місяць 1–2 дні

App Shell архітектура та precaching критичних ресурсів при першому встановленні дають миттєве завантаження оболонки додатку навіть при повільному з'єднанні.

Процес роботи та терміни

  1. Аудит поточного додатку (Lighthouse PWA score, аналіз сценаріїв).
  2. Визначення цінних офлайн-сценаріїв.
  3. Налаштування Service Worker через Workbox та реалізація маніфесту.
  4. Інтеграція Web Push (якщо потрібно).
  5. Тестування на реальних пристроях — Chrome DevTools, Safari Web Inspector.
  6. Деплой, документація, навчання команди.

Орієнтовні терміни: базова PWA (маніфест + Service Worker + кеш статики) — 1–2 тижні поверх готового додатку; Web Push — 1–2 тижні; офлайн-редагування з IndexedDB та Background Sync — 3–6 тижнів залежно від складності даних.

Вартість розраховується індивідуально після аудиту. PWA-проект зазвичай обходиться в 2–3 рази дешевше нативного додатку під обидві платформи. Додаткову економію дає відсутність витрат на публікацію в App Store та Google Play. Зв'яжіться з нами для консультації — ми безкоштовно оцінимо ваш проект та запропонуємо оптимальну стратегію впровадження.

Посилання для поглибленого вивчення