Как создать несколько PWA, используя одно и то же доменное имя, чтобы дать пользователю понять, что он принадлежит к одной и той же организации или службе.
В записи блога «Прогрессивные веб-приложения на сайтах с несколькими источниками» Демиан обсудил проблемы, с которыми сталкиваются сайты, созданные на основе нескольких источников, при попытке создать единое прогрессивное веб-приложение, которое охватывало бы все из них.
Примером такого типа архитектуры сайта является сайт электронной коммерции, где:
- Домашняя страница находится по адресу
https://www.example.com
. - Страницы категорий размещены по адресу
https://category.example.com
. - Страницы с подробной информацией о продукте по адресу
https://product.example.com
.
Как обсуждалось в статье, политика единого источника накладывает ряд ограничений, препятствуя совместному использованию сервис-воркеров, кэшей и разрешений между источниками. По этой причине мы настоятельно рекомендуем избегать такого типа конфигурации, а тем, у кого уже есть сайты, построенные таким образом, рассмотреть возможность перехода на архитектуру с единым источником, если это возможно.

В этой статье мы рассмотрим противоположный случай: вместо одного PWA из разных источников мы проанализируем случай компаний, которые хотят предоставлять несколько PWA , используя одно и то же доменное имя , и информировать пользователя о том, что эти PWA принадлежат одной и той же организации или службе.
Как вы могли заметить, мы используем разные, но взаимосвязанные термины, такие как «домены» и «источники». Прежде чем двигаться дальше, давайте рассмотрим эти понятия.
Технические термины
- Домен: любая последовательность меток, определённая в системе доменных имён (DNS). Например,
com
иexample.com
— это домены. - Имя хоста: DNS-запись, которая разрешается как минимум в один IP-адрес. Например,
www.example.com
будет именем хоста,example.com
мог бы быть именем хоста, если бы у него был IP-адрес, аcom
никогда не будет разрешаться в IP-адрес и, следовательно, никогда не сможет быть именем хоста. - Источник: комбинация схемы, имени хоста и (необязательно) порта. Например,
https://www.example.com:443
— это источник.
Как следует из названия, политика единого источника накладывает ограничения на источники, поэтому в статье мы будем в основном использовать этот термин. Тем не менее, мы будем время от времени использовать термины «домены» или «поддомены» для описания используемого метода создания различных источников.
Аргументы в пользу множественных связанных PWA
В некоторых случаях может возникнуть необходимость создавать независимые приложения, но при этом указывать их принадлежность к одной и той же организации или «бренду». Повторное использование одного и того же доменного имени — хороший способ установить эту связь. Например:
- Сайт электронной коммерции хочет создать отдельный интерфейс, позволяющий продавцам управлять своими товарами, при этом давая им понять, что он принадлежит основному сайту, где пользователи покупают товары.
- Сайт спортивных новостей хочет создать специальное приложение для крупного спортивного события, чтобы пользователи могли получать статистику о своих любимых соревнованиях с помощью уведомлений, и установить его как Progressive Web App, при этом убедившись, что пользователи распознают его как приложение, созданное новостной компанией.
- Компания хочет создать отдельные приложения для чата, почты и календаря и хочет, чтобы они работали как отдельные приложения, привязанные к названию компании.

Использование отдельных источников
Рекомендуемый подход в подобных случаях — размещать каждое концептуально отличное приложение на своем собственном источнике.
Если вы хотите использовать одно и то же доменное имя внутри всех этих сайтов, вы можете сделать это с помощью поддоменов. Например, компания, предоставляющая несколько интернет-приложений или услуг, может разместить почтовое приложение на https://mail.example.com
и приложение календаря на https://calendar.example.com
, предлагая основную услугу своего бизнеса на https://www.example.com
. Другой пример — спортивный сайт, который хочет создать независимое приложение, полностью посвященное важному спортивному событию, например, чемпионату по футболу на https://footballcup.example.com
, которое пользователи смогут установить и использовать независимо от основного спортивного сайта, размещенного на https://www.example.com
. Этот подход также может быть полезен для платформ, которые позволяют клиентам создавать собственные независимые приложения под брендом компании. Например, приложение, позволяющее продавцам создавать собственные PWA на https://merchant1.example.com
, https://merchant2.example.com
и т. д.
Использование разных источников обеспечивает изоляцию между приложениями, что означает, что каждое из них может независимо управлять различными функциями браузера, включая:
- Возможность установки: каждое приложение имеет собственный манифест и обеспечивает собственный опыт установки.
- Хранилище: каждое приложение имеет собственный кэш, локальное хранилище и, по сути, все формы локального хранилища устройства, не разделяя их с другими.
- Service Workers: Каждое приложение имеет своего собственного service worker для зарегистрированных областей.
- Разрешения: Разрешения также ограничены источниками. Благодаря этому пользователи будут точно знать, для какого сервиса они предоставляют разрешения, а такие функции, как уведомления, будут правильно назначены каждому приложению.
Создание такой степени изоляции наиболее желательно в случае использования нескольких независимых PWA, поэтому мы настоятельно рекомендуем этот подход .
Если приложения на поддоменах захотят обмениваться локальными данными друг с другом, они по-прежнему смогут делать это с помощью файлов cookie, а в более сложных сценариях они могут рассмотреть возможность синхронизации хранилища через сервер.

Используя тот же источник
Второй подход заключается в создании различных PWA на одном и том же источнике. Это включает следующие сценарии:
Непересекающиеся пути
Несколько PWA или концептуальных «веб-приложений», размещённых на одном источнике, с непересекающимися путями. Например:
-
https://example.com/app1/
-
https://example.com/app2/
Перекрывающиеся/вложенные пути
Несколько PWA в одном источнике, область действия одного из которых вложена в область действия другого:
-
https://example.com/
(«внешнее приложение») -
https://example.com/app/
(«внутреннее приложение»)
API сервис-воркера и формат манифеста позволяют реализовать любой из вышеперечисленных вариантов, используя область видимости на уровне пути. Однако в обоих случаях использование одного и того же источника создаёт множество проблем и ограничений, основная причина которых заключается в том, что браузер не будет полностью рассматривать их как отдельные «приложения», поэтому такой подход не рекомендуется .

В следующем разделе мы более подробно проанализируем эти проблемы и что можно сделать, если использование отдельных источников невозможно.
Проблемы с несколькими PWA одного происхождения
Вот некоторые практические вопросы, общие для обоих подходов, основанных на едином происхождении:
- Хранилище: файлы cookie, локальное хранилище и все формы локального хранилища устройства используются приложениями совместно. Поэтому, если пользователь решит удалить локальные данные одного приложения, будут удалены все данные из источника; для отдельного приложения это сделать невозможно. Обратите внимание, что Chrome и некоторые другие браузеры будут автоматически предлагать пользователям удалить локальные данные при удалении одного из приложений, и это повлияет на данные других приложений в источнике. Другая проблема заключается в том, что приложениям также придётся делиться своей квотой хранилища, а это означает, что если одно из них займёт слишком много места, другое пострадает.
- Разрешения: Разрешения браузера привязаны к источнику. Это означает, что если пользователь предоставляет разрешение одному приложению, оно будет применяться ко всем приложениям в этом источнике одновременно. Это может показаться полезным (не нужно запрашивать разрешение несколько раз), но помните: если пользователь заблокирует разрешение одному приложению, это не позволит другим запрашивать это разрешение или использовать эту функцию. Обратите внимание, что даже если разрешения браузера нужно предоставлять только один раз для каждого источника, разрешения системного уровня, с другой стороны, должны предоставляться один раз для каждого приложения, независимо от того, указывают ли несколько приложений на один и тот же источник.
- Пользовательские настройки: настройки также задаются для каждого источника. Например, если в двух приложениях разный размер шрифта, и пользователь хочет изменить масштаб только в одном из них, чтобы компенсировать разницу, он не сможет сделать это, не применив настройки и к другим приложениям.
Эти проблемы затрудняют поддержку такого подхода. Тем не менее, если вы не можете использовать отдельный источник (например, поддомен), как обсуждалось в разделе «Использование отдельных источников» из двух представленных нами вариантов с одним источником, настоятельно рекомендуется использовать непересекающиеся пути, а не перекрывающиеся/вложенные пути.
Как уже упоминалось, проблемы, обсуждаемые в этом разделе, являются общими для обоих подходов с общим источником. В следующем разделе мы подробнее рассмотрим, почему использование перекрывающихся/вложенных путей является наименее рекомендуемой стратегией.
Дополнительные проблемы для перекрывающихся/вложенных путей
Дополнительная проблема с подходом с перекрывающимися/вложенными путями (где https://example.com/
— внешнее приложение, а https://example.com/app/
— внутреннее приложение) заключается в том, что все URL-адреса во внутреннем приложении фактически будут считаться частью как внешнего, так и внутреннего приложения.
На практике это приводит к следующим проблемам:
- Реклама установки: если пользователь заходит во внутреннее приложение (например, в веб-браузере), когда внешнее приложение уже установлено на устройстве пользователя, браузер не отображает рекламные баннеры, предлагающие установку, и событие BeforeInstallPrompt не срабатывает. Это связано с тем, что браузер проверяет, принадлежит ли текущая страница уже установленному приложению, и делает вывод, что да. Обходной путь — установить внутреннее приложение вручную (через пункт меню браузера «Создать ярлык») или сначала установить внутреннее приложение, а затем внешнее.
- API уведомлений и бейджинга : если внешнее приложение установлено, а внутреннее — нет, уведомления и бейджи, исходящие от внутреннего приложения, будут ошибочно приписываться внешнему приложению (которое является ближайшей охватывающей областью установленного приложения). Эта функция работает корректно, если на устройстве пользователя установлены оба приложения.
- Захват ссылок : Внешнее приложение может захватывать URL-адреса, принадлежащие внутреннему приложению. Это особенно вероятно, если внешнее приложение установлено, а внутреннее — нет. Аналогично, ссылки внутри внешнего приложения, ведущие на внутреннее приложение, не будут захватывать ссылки во внутреннее приложение, поскольку они считаются находящимися в области действия внешнего приложения. Кроме того, в ChromeOS и Android, если эти приложения добавлены в Play Store (как доверенные веб-активности ), внешнее приложение будет захватывать все ссылки. Даже если внутреннее приложение установлено, ОС всё равно предложит пользователю открыть их во внешнем приложении.
Заключение
В этой статье мы рассмотрели различные способы, с помощью которых разработчики могут создавать несколько прогрессивных веб-приложений, связанных друг с другом в пределах одного домена .
Подводя итог, мы настоятельно рекомендуем использовать разные источники (например, поддомены) для размещения независимых PWA. Размещение их в одном источнике сопряжено с рядом сложностей, главным образом потому, что браузер не всегда воспринимает их как отдельные приложения.
- Отдельные источники: рекомендуется
- Один и тот же источник, непересекающиеся пути: не рекомендуется
- Один и тот же источник, перекрывающиеся/вложенные пути: настоятельно не рекомендуется
Если невозможно использовать разные источники, настоятельно рекомендуется использовать непересекающиеся пути (например, https://example.com/app1/
и https://example.com/app2/
, а не перекрывающиеся или вложенные пути, например, https://example.com/
(для внешнего приложения) и https://example.com/app/
(для внутреннего приложения).
Дополнительные ресурсы
Выражаем огромную благодарность за технические обзоры и предложения: Джо Медлей, Доминику Нг, Алану Каттеру, Дэниелу Мерфи, Пенни Маклахлан, Томасу Штайнеру и Дарвину Хуангу.
Фото Тима Мосхолдера на Unsplash