РозробкаБудь-який рівень

PWA

PWA (progressive web app) — це не фреймворк і не формат, а набір можливостей браузера, які дозволяють сайту встановитися на домашній екран, працювати офлайн і поводитися як застосунок. SDK для PWA не існує: ви додаєте service worker, маніфест і HTTPS, а що з цього вийде — залежить від того, який у користувача браузер. На цій сторінці — service worker, встановлюваність, що насправді дозволяє iOS і як чесно вибирати між PWA та нативним застосунком.

Що це
Можливості браузера
Потребує
HTTPS, воркер, маніфест
Дистрибуція
Посилання, без рев’ю

Service worker

Усе, що PWA вміє, а звичайний сайт — ні, походить з одного механізму. Service worker — це скрипт, який браузер виконує поза сторінкою, і щойно його зареєстровано, кожен мережевий запит сторінки спершу проходить крізь нього. Для кожного воркер вирішує: відповісти з кешу, піти в мережу чи зробити і те, і те й обрати. Сторінка про це не здогадується й обійти це не може.

Service worker — це скрипт, який браузер тримає поза сторінкою, і крізь нього проходить кожен запит сторінки. Для кожного запиту він вирішує, відповісти з кешу чи піти в мережу, — і саме це взагалі уможливлює офлайн, миттєві повторні завантаження та фонову синхронізацію. Той самий задум створює й проблему оновлення: новий воркер встановлюється, але чекає, доки закриють усі вкладки зі старим, тож випущене виправлення не доходить до користувачів на наступному завантаженні, якщо сторінка не обробляє оновлення свідомо.

Яку стратегію взяти — рішення на кожен запит, а не глобальне налаштування, і полягає воно в тому, наскільки застарілою може бути відповідь. Оболонку застосунку — HTML, CSS і JavaScript — віддавайте спершу з кешу, бо вони версіоновані, і копія в кеші коректна аж до вашого розгортання. Дані API віддавайте спершу з мережі з відкотом до кешу: користувач зі зв’язком побачить актуальне, а користувач у тунелі — те останнє, що мав. Беріть stale-while-revalidate там, де миттєво важить більше за свіжо: показати кеш одразу, сходити в мережу у фоні, оновити на наступний раз.

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

Що робить його встановлюваним

Друга половина PWA — це вебманіфест: маленький JSON-файл, що називає застосунок, його іконки, колір теми, стартову URL і режим показу. Поставте display у standalone — і встановлений застосунок відкриється без обрамлення браузера: без адресного рядка й вкладок, — а це й є більша частина того, що робить його схожим на застосунок, а не на закладку. Віддавайте це через HTTPS, який для service worker потрібен так чи інакше.

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

Межі, названі чесно

Можливості PWA — не одна річ, а список API, кожен з яких підтримують одні браузери й не підтримують інші, і розрив розподілений нерівномірно. Браузери на Chromium під Android реалізують майже все. Safari на iOS реалізує ядро й лишає поза дужками кілька речей, які команди схильні вважати даністю, — а оскільки PWA на iOS працює в рушії Safari незалежно від того, який браузер його встановив, обійти це неможливо.

МожливістьAndroid / ChromiumiOS / Safari
Офлайн і кешуванняПовна підтримкаПідтримується; сховище можуть очистити при простої
Встановлення на домашній екранБраузер сам пропонуєВручну через меню поділитися — користувачам треба пояснити
Пуш-сповіщенняТакЛише коли встановлено на домашній екран
Фонова синхронізаціяТакНі
Bluetooth, NFC, USBТак, за дозволомНі

Рішення, до якого це веде, простіше, ніж підказує порівняння. Якщо продукт — це контент, комерція, бронювання, дашборди чи внутрішні інструменти, тобто по суті сайт, якому було б корисно працювати офлайн і жити на домашньому екрані, — PWA дешевша відповідь і доходить до всіх через посилання. Якщо продукт залежить від доступу до заліза, від поведінки у фоні, поки він закритий, від знаходжуваності в магазині чи від присутності на ринку, де застосунки шукають, гортаючи магазин, — це має бути застосунок. Усе між цими полюсами — судження про те, скільки коштує вам відсутня можливість.

Як це виявляється в реальній поставці

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

Дві речі треба проєктувати, а не припускати. Сховище не є постійним: браузер може витіснити дані сайту під тиском або після довгого простою, тож усе, що користувачеві було б прикро втратити, має дійти до сервера, а navigator.storage.persist() — це прохання, а не гарантія. І офлайн — це стан, який має бути в інтерфейсі, а не технічна деталь: показуйте, що є в кеші, позначайте застаріле, ставте в чергу те, що записали без зв’язку, і кажіть користувачеві, на що саме він дивиться. Застосунок, який мовчки показує тижневі дані як актуальні, гірший за той, що зізнається, що він офлайн.

Де це вироджується

  • Оновлення не обробляється — випущене виправлення чекає за старим воркером, доки відкрита вкладка.
  • Написаний руками service worker, чий список кешу розходиться з виходом збірки.
  • Закешований сам файл service worker може лишити користувачів на версії, яку ви не заміните.
  • Стратегія «спершу кеш» для даних API — застосунок упевнено показує інформацію кількаденної давнини.
  • Офлайн як стан помилки, а не спроєктований стан, — і в результаті порожній екран.
  • Дані, що живуть лише у сховищі браузера, яке той має право очистити.
  • Фіча, спланована на API, якого iOS не реалізує, виявлена вже після затвердження дизайну.

Коли це застосовувати

Застосовуйте, коли

  • Продукти, які по суті є сайтом і виграли б від офлайну та іконки на домашньому екрані.
  • Усе, що знаходять пошуком або передають посиланням, де крок встановлення коштує вам користувачів.
  • Внутрішні інструменти та польові застосунки, де пристрої ваші, а черга рев’ю — чисті накладні витрати.
  • Команди, яким потрібна одна кодова база на десктоп і мобільні й немає людей на дві нативні платформи.

Уникайте, коли

  • Застосунки з доступом до заліза — Bluetooth, NFC, USB — на iOS, де цих API просто немає.
  • Усе, що залежить від роботи, поки застосунок закритий: вебплатформа цього не гарантує.
  • Продукти, чиї користувачі шукають застосунки, гортаючи магазин, — туди посилання не доходить.
  • Досвід із важкою графікою чи критичною затримкою, де браузер — хибне середовище виконання.

Було корисно?

Поділіться з тим, хто працює над тією ж задачею.