# Маніфест вебдодатка

## Що це таке

Маніфест вебдодатка — це документ JSON, який описує вебсайт як застосунок: як
він називається, з якої адреси відкривається, які адреси йому належать, яким має
бути його вікно і які зображення його представляють. Сторінка вказує на файл
елементом `link`, у якого `rel` дорівнює `manifest`, а браузер, що пропонує
встановлення, читає цей файл, щоб вирішити, яким буде встановлений примірник.
Специфікація W3C, яка визначає формат, називає його просто маніфестом, і в
повсякденній мові його звуть так само.

Файл — це звичайний JSON. Його зареєстрований медіатип —
`application/manifest+json`, а зареєстроване розширення — `.webmanifest`, хоча
специфікація приймає будь-який медіатип JSON, і чимало сайтів віддають файл
`manifest.json`. Усі поля необов'язкові. Невеликий маніфест для вигаданого сайту
з таблицями припливів у гавані може мати такий вигляд:

```json
{
    "name": "Таблиці припливів гавані",
    "short_name": "Припливи",
    "start_url": "/pryplyvy/",
    "display": "standalone",
    "background_color": "#ffffff",
    "icons": [
        {
            "src": "/icons/pryplyvy-512.png",
            "sizes": "512x512",
            "type": "image/png"
        }
    ]
}
```

Три поля визначають, чим є застосунок, на відміну від того, який він має вигляд.
`start_url` — це сторінка, з якої відкривається встановлений застосунок. `scope`
— це набір адрес, що вважаються частиною застосунку; якщо його не вказано,
специфікація бере початкову адресу й відкидає ім'я файлу, запит і фрагмент, тож
приклад вище охоплює все під `/pryplyvy/`. `id` — це ідентичність застосунку, а
коли його немає, нею стає початкова адреса. Відносні адреси у файлі, і для
значків, і для початкової сторінки, розв'язуються відносно адреси самого
маніфесту, а не сторінки, яка на нього послалася.

Решта стосується вигляду. `display` просить `fullscreen`, `standalone`,
`minimal-ui` або `browser`, а браузер, що не може виконати прохання, спускається
цим списком саме в такому порядку. Кожен значок може мати `purpose`: усталено
`any`, `maskable` для зображення, намальованого так, щоб пережити обрізання, або
`monochrome` для такого, колір якого відкидають і використовують лише
альфа-канал. `theme_color` фарбує вікно навколо застосунку. Супровідна нотатка
W3C додає `description`, `categories` і `screenshots`, які можуть показувати
діалоги встановлення й магазини застосунків.

## Чому це важливо

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

Ідентичність — це обіцянка, яка живе довше за файл. Коли браузер знову
завантажує маніфест, специфікація вимагає від нього за `id` визначити, чи
стосується новий файл уже встановленого застосунку. Оскільки відсутній `id`
дорівнює початковій адресі, перенесення стартової сторінки непомітно змінює
ідентичність, і новий файл тоді описує інший застосунок, ніж той, що стоїть на
пристрої читача. Закріпити `id` у першому випуску коштує один рядок і прибирає
цей ризик.

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

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

Поля кольору важать менше, ніж здається. `background_color` призначено лише для
моменту, поки не надійшла таблиця стилів, і специфікація забороняє браузерові
використовувати його, щойно таблиця стилів готова. Це колір першого кадру, і
нічого після нього.

## Як це виглядає на практиці

Цей сайт будує маніфест із шаблону, а не тримає файл, написаний вручну.
Конфігурація Hugo реєструє `application/manifest+json` із суфіксом `webmanifest`
і робить маніфест вихідним форматом головної сторінки кожної мови, тож кожна
мова отримує власний файл, а заголовна частина кожної сторінки посилається на
файл своєї мови. Конфігурація записує й причину: одна спільна копія може назвати
лише одну початкову адресу, і данський відвідувач, який установив сайт, отримав
застосунок, що відкривав англійську головну сторінку.

Шаблон складає маніфест через `dict` у Hugo й передає його JSON-кодувальникові
Hugo, тож екранування й коми — турбота кодувальника, і пропущена кома ніколи не
потрапить у випуск. Кожна адреса значка починається від кореня хоста, і коментар
у шаблоні пояснює чому: відносна адреса в `/da/manifest.webmanifest`
розв'язувалася б під `/da/`, і кожен значок данською повертав би 404. Самі
значки зчитуються з диска з трьох тек, по одній на кожне призначення, по десять
розмірів від 36 до 512 пікселів у кожній, а розмір береться з імені файлу, тож
розмір, доданий генератором, з'являється в маніфесті без жодного редагування.

`id` закріплено за адресою головної сторінки мови, а `scope` охоплює весь
origin, тож посилання на іншу мову лишається у встановленому вікні. Знімки
екрана мають імена `<lang>-<form_factor>-<WxH>.webp`, і шаблон зчитує всі три
відомості з імені файлу: англійська й данська мають по одному широкому знімку
1280 на 800 і по одному вузькому 780 на 1688. Мова без знімків не отримує поля
`screenshots` зовсім, бо порожній список стверджував би, що застосункові нічого
показати.

[Сторінка подяк](/uk/credits/) називає специфікацію W3C серед стандартів, яких
дотримується сайт, а PWABuilder — серед зовнішніх перевірок, які кожен може
запустити сам: це сервіс на серверах Microsoft, що перевіряє маніфест і все
інше, від чого залежить встановлення.

[Сторінка встановлення](/uk/install/) — це половина того самого файлу, звернена
до читача. Вона пояснює, де кожен браузер тримає команду встановлення, зазначає,
що браузери Apple ніколи не пропонують її самі, а Firefox на комп'ютері
вебзастосунків узагалі не встановлює, і налаштовує очікування: встановлений
застосунок — це значок і власне вікно, і йому потрібне з'єднання, бо робота без
мережі вимагає service worker.

## Де виникають проблеми

**Кожен значок повертає 404 на перекладеному шляху.** Відносний `src`
розв'язується відносно адреси маніфесту, тож маніфест, відданий з-під мовного
префікса, просить значки під тим самим префіксом. Пишіть адреси значків від
кореня хоста або як повні URL.

**Встановлений застосунок відкривається не тією мовою.** Один маніфест може
назвати одну початкову адресу, тож усі читачі встановлюють ту саму головну
сторінку. Віддавайте окремий маніфест для кожної мови з власними `start_url` та
`id` і посилайтеся з кожної сторінки на відповідний.

**Встановлені копії ігнорують новий маніфест.** Без `id` ідентичністю є
початкова адреса, тож коли стартову сторінку переносять, файл отримує нову
ідентичність, і браузер більше не застосовує його до застосунку, який читачі вже
мають. Задайте `id` до першого випуску й надалі його не змінюйте.

**Домашній екран обрізає логотип.** Значок із призначенням `any` розміщують чи
обрізають так, як вважає за потрібне платформа. Додайте значок `maskable`, у
якого все важливе лежить усередині центрального кола з радіусом 40% від розміру
значка.

**Зміни в маніфесті ні на що не впливають.** Стандарт HTML використовує лише
перший елемент `link`, чий `rel` містить `manifest`, тож якщо тема чи плагін уже
вставили власне посилання вище на сторінці, файл, який редагують, браузер так і
не прочитає. Тримайте на сторінці рівно одне посилання на маніфест.

## Що почитати далі

- [Web Application Manifest](https://www.w3.org/TR/appmanifest/) — усі поля, те,
  як браузер обробляє файл, і правила для `id`, `scope` та призначень значків.
- [Web App Manifest - Application Information](https://www.w3.org/TR/manifest-app-info/)
  — `description`, `categories` і `screenshots` разом із форм-факторами й
  підписами.
- [IANA: application/manifest+json](https://www.iana.org/assignments/media-types/application/manifest+json)
  — реєстрація медіатипу та його розширення `.webmanifest`.
- [HTML Standard: link type manifest](https://html.spec.whatwg.org/multipage/links.html#link-type-manifest)
  — як завантажується посилання на маніфест і чому зважають лише на перше.

<https://engineer.company/uk/glossary/webmanifest/>
