Прогрессивное веб-приложение (или PWA) - это веб-приложение, которое предоставляет набор возможностей, позволяющих сделать веб-сайты похожими на приложения. Лично я всегда чувствую, что слишком много веб-сайтов создают собственные приложения, которые практически не предоставляют (или даже меньше) дополнительных функций для своих веб-сайтов, за исключением возможности иметь ярлык. Вот где PWA могут сыграть решающую роль. Начиная с Chrome 72 для Android, функция Trusted Web Activity была отправлена, что означает, что PWA могут быть распространены в магазине Google Play, что свидетельствует о важности этого развития.

При создании веб-сайтов разработчикам приходится сталкиваться с несколькими проблемами. Скорость интернета не так высока во всем мире, как вы привыкли к себе. Веб-сайт должен быть эффективным, чтобы пользователю не приходилось ждать, пока он взаимодействует с веб-сайтом. Также оказывается, что пользователи не часто устанавливают нативные приложения просто потому, что порог слишком высок. Все эти проблемы решаются с помощью PWA.

PWA работают быстро, потому что приложение устанавливается либо вручную, либо через сервис-воркера на устройстве. Данные кешируются, и мы можем обновлять приложение при появлении новых изменений. PWA ведут себя как собственные приложения, что означает, что они могут обеспечить более плавный и интегрированный опыт, а также предоставляют такие преимущества собственных приложений, как push-уведомления. Благодаря стратегиям кэширования они могут рисовать картинку на экране пользователя, когда нет сети. Это делает их более надежными.

Существует множество статей о том, как запустить новое приложение Angular PWA, поэтому мы сосредоточимся на обновлении существующего приложения. Для этого мы будем использовать AngularCLI и Angular 7, поскольку это все инструменты, которые нам нужны. Предполагается, что вы, как читатель, уже имеете хорошее представление о том, что такое сервис-воркер.

Изменить: репозиторий Github, принадлежащий этой статье, был обновлен до Angular версии 9.1.0, которую вы можете использовать для кикстарта вашего проекта.

Делаем приготовления

Мы собираемся добавить @angular/pwa в наш пакет через AngularCLI, который выполняет следующие действия:

  1. Добавляет пакет @angular/service-worker в ваш проект.
  2. Включает поддержку сборки сервис-воркера в интерфейсе командной строки.
  3. Импортирует и регистрирует сервис-воркер в модуле приложения.
  4. Обновляет файл index.html, включая ссылку на файл manifest.json, и добавляет метатеги для theme-color. Измените цвет этой темы вручную на цвет, подходящий для вашего приложения.
  5. Устанавливает файлы значков для поддержки установленного PWA.
  6. Создает файл конфигурации сервис-воркера с именем ngsw-config.json, который определяет поведение кэширования и другие параметры.

Используйте это в папке своего проекта:

ng add @angular/pwa

На момент написания (Angular 7.2.9 и @ angular / pwa 0.13.6) нам также нужно сделать небольшое обходное решение в main.ts, чтобы правильно зарегистрировать сервис-воркер. (Угловой выпуск # 8779)

platformBrowserDynamic().bootstrapModule(AppModule).then(() => {
  if ('serviceWorker' in navigator && environment.production) {
    navigator.serviceWorker.register('/ngsw-worker.js');
  }
}).catch(err => console.log(err));

И этот фрагмент выше, и изменения, внесенные в app.module.ts, создают ссылку на ngsw-worker.js файл, который вы не видите в своем проекте. Не волнуйся! Сборка Angular-CLI создаст это за вас, когда вы создадите свое приложение.

Структура PWA

Manifest.json

Для запуска PWA нам понадобится несколько дополнительных файлов. Во-первых, нам нужен manifest.json, который представляет собой манифест веб-приложения: простой файл JSON, который сообщает браузеру о вашем веб-приложении и его поведении при установке на мобильное устройство или рабочий стол пользователя.

Примечательными атрибутами в этом манифесте являются name, short_name, description, theme_color и background_color. Убедитесь, что они введены правильно. short_name используется в качестве имени вашего приложения при добавлении на главный экран, поэтому обязательно добавьте его.

ngsw-config.json

Вышеупомянутые шаги также сгенерировали ngsw-config.json файл, который содержит конфигурацию того, как процесс сборки Angular будет создавать вашего сервис-воркера. Позже мы подробно обсудим наиболее важные настройки.

Иконки

Значки важнее, чем вы думаете, поэтому убедитесь, что вы создали их в предложенных размерах. Если вы практичны, вы можете использовать один из множества доступных онлайн-генераторов значков избранного. Убедитесь, что существуют значки размером 192 x 192 пикселей и 512 x 512 пикселей, поскольку они используются Android для отображения запроса установки Добавить на главный экран и используются Microsoft Store для автоматического индексирования и упаковки вашего приложения.

Если вы посмотрите на manifest.json, вы увидите узел icons. Обратите внимание на размеры, которые создаются автоматически. Мой совет - убедитесь, что у вас есть подходящие иконки для всех этих размеров.

"icons": [
  (...)
  {
    "src": "assets/icons/icon-192x192.png",
    "sizes": "192x192",
    "type": "image/png"
  },
  {
    "src": "assets/icons/icon-512x512.png",
    "sizes": "512x512",
    "type": "image/png"
  }
]

К сожалению, iOS от Apple все еще несколько отстает в поддержке PWA. Чтобы убедиться, что ваше приложение также имеет значок на устройствах iOS, добавьте эти строки в тег заголовка index.html. Убедитесь, что файлы, на которые есть ссылки, имеют соответствующий размер.

<link rel="apple-touch-icon" href="/assets/icons/apple-touch-icon-iphone.png"/>
<link rel="apple-touch-icon" sizes="152x152" href="/assets/icons/apple-touch-icon-iphone.png"/>
<link rel="apple-touch-icon" sizes="167x167" href="/assets/icons/apple-touch-icon-ipad-retina.png"/>
<link rel="apple-touch-icon" sizes="180x180" href="/assets/icons/apple-touch-icon-iphone-retina.png"/>

ngsw-config.json

Как было сказано ранее, ngsw-config.json содержит настройки того, как процесс сборки Angular-CLI будет создавать вашего сервис-воркера. Конфигурация по умолчанию будет в основном состоять из атрибута index, обычно указывающего на ваш index.html, и assetGroups. С помощью этого последнего атрибута вы можете указать, какие файлы будут использовать определенную стратегию установки или обновления.

{
  "index": "/index.html",
  "assetGroups": [
    {
      "name": "app",
      "installMode": "prefetch",
      "resources": {
        "files": [
          "/favicon.ico",
          "/index.html",
          "/*.css",
          "/*.js"
        ]
      }
    }, {
      "name": "assets",
      "installMode": "lazy",
      "updateMode": "prefetch",
      "resources": {
        "files": [
          "/assets/**",
          "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
        ]
      }
    }
  ]
}

Установить стратегию

Эта стратегия заключается в том, чтобы сообщить приложению, как оно должно установить приложение на устройство пользователя. По умолчанию ngsw-worker.js установил стратегию установки (installMode) на prefetch, что означает, что все указанные файлы будут извлечены во время кэширования текущей версии приложения. Это требует большой пропускной способности, но обеспечивает доступность ресурсов всякий раз, когда они запрашиваются, даже если браузер в настоящее время отключен.

{
  "name": "app",
  "installMode": "prefetch",
  "resources": {
    "files": [
      "/favicon.ico",
      "/index.html",
      "manifest.json",
      "/*.css",
      "/*.js"
    ]
  }
}

Альтернативная стратегия - lazy, что означает, что ресурсы будут устанавливаться только по запросу. Обычно эта стратегия используется только для кэширования активов, как описано ниже!

Кэширование активов

Ваши активы по умолчанию настроены как assetsGroup assets. Опять же, у нас есть стратегии упреждающей выборки и отложенной загрузки.

{
  "name": "assets",
  "installMode": "lazy",
  "updateMode": "prefetch",
  "resources": {
    "files": [
      "/assets/**",
      "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
    ]
  }
}

Обратите внимание, что для installMode установлено значение lazy, а для updateMode установлено значение prefetch, что означает, что активы будут загружаться по запросу, но если активы уже были кэшированы, они будут активно обновляться. Если вы хотите добавить ресурсы с внешних серверов или CDN (например, шрифты Google), измените resources следующим образом:

"resources": {
  "files": [
    "/assets/**",
    "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
  ],
  "urls": [
    "https://fonts.googleapis.com/**"
  ]
}

Группы данных

Группы данных отличаются от ресурсов в том смысле, что они не упакованы с версией вашего приложения. Например, они могут поступать из API. Их можно кэшировать с помощью двух разных стратегий: freshness и performance.

Стратегия freshness полезна для ресурсов, которые часто меняются, и вы не хотите показывать устаревшие данные для. Эта стратегия всегда будет пытаться получить новую версию ресурса перед возвратом в кеш.

"dataGroups": [{
  "name": "api-freshness",
  "urls": [ "https://my.apipage.com/user" ],
  "cacheConfig": {
    "strategy": "freshness",
    "maxSize": 5,
    "maxAge": "1h",
    "timeout": "3s"
  }
}]

Этот фрагмент получит данные от конечной точки / user и будет кэшироваться не более 1 часа, не более 5 ответов и тайм-аута 3 секунды. После этого он вернется в кеш.

Стратегия performance, стратегия по умолчанию, более полезна для ресурсов, которые не сильно меняются. Он всегда будет показывать кешированную версию ресурса, если она доступна, но это, очевидно, может привести к устареванию ответа.

Тест-драйв!

Теперь, когда вы запускаете свое приложение с ng serve и проверяете вкладку «Приложение» в DevTools, вы можете заметить, что ни один сервис-воркер не был зарегистрирован. Функция Angular-CLI serve не поддерживает сервис-воркеров, поэтому сервис-воркер не появляется.

Мы собираемся найти, на мой взгляд, неприятный обходной путь, выполнив производственную сборку и обслуживая ее независимо.

npm i -g http-server
ng build --prod
http-server -p4200 -c-1 dist/<name-of-app>

Мне лично нравится устанавливать порт этого сервера на 4200, потому что, когда я набираю «l» в строке URL-адресов, первым появляется предложение «http: // localhost: 4200», которое соответствует ng serve.

Теперь, когда мы заходим на localhost: 4200 и проверяем вкладку приложения в DevTools. Если вы видите это, то сервисный работник успешно зарегистрировался.

Когда вы смотрите на вкладку «Сеть» и обновляете (не жесткое обновление), вы можете увидеть разницу в запросах. Слева вы видите, что столбец размера показывает размер загруженного пакета, а справа вы видите, что он был загружен из сервис-воркера.

Однако, если вы просматриваете это на мобильном устройстве, вы не увидите запроса «Добавить на главный экран» от Android. Они будут загружаться только через HTTPS-соединение, так что имейте это в виду, когда будете тестировать свое приложение в реальных условиях.

Полный пример

Вы можете найти очень простую реализацию на https://github.com/arjenbrandenburgh/medium-pwa-example. Существует отдельная фиксация, превращающая приложение в PWA, поэтому вы можете четко видеть, что изменилось.

Больше функциональности

У нас запущен сервис-воркер, файлы предварительно загружаются, а сервисы кэшируются. Люди могут установить наше приложение через подсказку «Добавить на главный экран» и могут взаимодействовать с приложением, как с собственным приложением. Хотя это уже звучит как огромный шаг вперед, у нас гораздо больше возможностей.

В этой статье я не буду обсуждать и показывать, как мы можем расширить эти функции, а скорее проинформирую вас о том, что возможно и доступно. Прочтите мою статью о SwPush и SwUpdate для более подробного объяснения.

SwUpdate: уведомляйте пользователей об обновлениях

Вы можете использовать @angular/service-worker SwUpdate для запуска проверок обновлений и принудительного обновления. Например, когда ваши пользователи используют приложение или веб-сайт, а вы только что развернули новую версию, вы можете запустить модальный или тостер, информирующий пользователей об этом обновлении, и попросить их перезагрузить, чтобы всегда иметь новейшие возможности.

SwPush: уведомления для взаимодействия

С @angular/service-worker SwPush мы можем подписаться и слушать push-уведомления от Service Worker. Для этого нам также нужен сервер, который, очевидно, действительно отправляет эти уведомления.

Резюме

В этой статье мы обсудили шаги, которые необходимо предпринять для обновления нашего текущего приложения до PWA. Мы видели, что с помощью нескольких простых шагов мы можем использовать Angular и Angular-CLI для создания мощного сервис-воркера, который позволит вашим пользователям более плавно работать с вашим веб-сайтом, при этом наслаждаясь преимуществами нативного приложения.