Если вы пользуетесь смартфоном (а кто не в наши дни?), Скорее всего, вы уже использовали прогрессивные веб-приложения (PWA). Это связано с тем, что PWA выглядят и ощущаются как собственные приложения, и их можно купить или загрузить в App Store или Google Play, как и любое другое собственное приложение. Тем не менее, PWA также могут выглядеть и работать как обычный веб-сайт, но с улучшенной производительностью. Так что же они из себя представляют и почему отраслевые гиганты, такие как Twitter, Pinterest и Starbucks, делают переход?

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

Давайте возьмем пример пользователя со старым смартфоном среднего уровня с медленным подключением к сети 3G. На традиционном веб-сайте браузер должен сделать несколько обращений к серверу, чтобы получить все, что ему нужно для визуализации начального представления. Это может занять удивительно много времени, особенно если речь идет о фотографиях с высоким разрешением. Кроме того, если пользователю нужно выбрать между удалением одного приложения и установкой другого, они с меньшей вероятностью загрузят его и, следовательно, с меньшей вероятностью будут взаимодействовать с продуктом. Twitter - отличный пример: после преобразования своего мобильного веб-сайта в PWA (он же «Twitter Lite») они перешли от интерактивности в сети 3G примерно за 15 секунд загрузки до менее чем 5 секунд! Количество твитов увеличилось на 76%, а количество просмотров страниц - на 2,7%.

И это потенциально может иметь еще большие последствия для разработчиков приложений: теперь вы можете написать универсальное мобильное приложение, использующее только JavaScript, CSS и HTML. Конечно, другие инструменты и фреймворки, такие как React, значительно облегчат вашу работу, но вам больше не нужно знать React Native, Swift, Java или Objective-C, чтобы предоставить пользователям опыт работы с приложением. Конечно, у PWA есть свои ограничения, и не каждая идея приложения подходит для использования фреймворка PWA (например, приложений, использующих Mapbox). Кроме того, такие компании, как Apple поставили некоторые препятствия для PWA в пользу нативных приложений. При этом давайте поговорим о том, как создать PWA.

Подготовка к настройке

Эти инструкции предполагают, что у вас есть редактор кода и способ запустить свой веб-сайт на локальном хосте с сервером разработки.

Во-первых, давайте подготовим наш основной HTML-документ. Обратите внимание, что этот пример HTML-документа настроен для Webpack для объединения моих файлов и запуска приложения React в div с идентификатором «app».

<!DOCTYPE html>
<html>
  <head>
    <meta charset=”utf-8" />
    <meta name=”viewport” content=”width=device-width 
    initial-scale=1.0" />
    <title>My App</title>
    <link rel=”stylesheet” href=”/style.css” />
    <link rel=”manifest” href=”/manifest.webmanifest” />
    <script defer src=”/bundle.js”></script>
    </head>
    <body>
    <div id=”app”></div>
    </body>
</html>

Здесь выделяется следующая важная строка кода:

<link rel=”manifest” href=”/manifest.webmanifest” />

Подобно тому, как мы подключаемся к нашей таблице стилей, здесь мы связываем наш манифест с нашим документом. Но что такое манифест, спросите вы?

Воплоти свои мечты

Чтобы сделать ваше веб-приложение доступным для установки, вам необходимо создать файл веб-манифеста. Манифест - это файл JSON, содержащий информацию о вашем приложении, включая значки, которые он должен использовать при установке вашего приложения. Создайте в общей папке файл с именем manifest.webmanifest и вставьте следующий код:

{
  “short_name”: “Your App Name”,
  “name”: “Your App Name: The Best App Around!”,
  “description”: “The app you’ve always needed and never knew it.”,
  “icons”: [
    {
      “src”: “/images/logoSmall.png”,
      “type”: “image/png”,
      “sizes”: “192x192”
    },
    {
      “src”: “/images/logoBig.png”,
      “type”: “image/png”,
      “sizes”: “512x512”
    }
  ],
  “start_url”: “/”,
  “background_color”: “#ffffff”,
  “display”: “standalone”,
  “scope”: “/”,
  “theme_color”: “#808080”,
  “shortcuts”: []
}

Обновите short_name, name и description по своему вкусу. Значки - это то, что устройство будет использовать при установке приложения на домашний экран или рабочий стол. Как минимум, вам понадобится логотип 192x192 пикселей и логотип 512x512 пикселей. Если у вас их нет, посетите https://favicon.io/, создайте логотип и загрузите папку с новыми логотипами. Создайте в общей папке папку под названием изображения и поместите в нее свои логотипы 192 и 512. Либо переименуйте изображения в logoSmall.png и logoBig.png, либо измените строки кода src: в манифесте, чтобы они совпадали с именами ваших значков. Цвет фона в настоящее время белый, а цвет темы серый. Вы также можете изменить их по своему вкусу.

С манифестом вы можете сделать больше, например добавить ярлыки или изменить отображение. Для получения дополнительной информации о настройке манифеста посетите этот ресурс: https://web.dev/add-manifest/

Найдите себе сервисного работника

Service worker - это сценарий, который запускается в фоновом режиме вашего браузера. Он может обеспечить автономные операции и повысить производительность за счет стратегий кэширования и использования времени простоя для загрузки ресурсов. Скрипт сервис-воркера должен быть реализован в заголовке вашего основного HTML-документа.

Добавьте следующий код в свой HTML-код прямо под скриптом bundle.js.

<script>
  if (‘serviceWorker’ in navigator) {
    window.addEventListener(‘load’, () => {
    navigator.serviceWorker.register(‘/service-worker.js’)
    })
  }
</script>

Этот код проверяет, поддерживает ли браузер сервис-воркера, и использует событие загрузки окна для регистрации вашего сервис-воркера. Теперь создайте файл service-worker.js в общей папке. Вот пример, взятый из примера github GoogleChrome для базового сервис-воркера, который вы можете вставить в service-worker.js:

/*
Copyright 2015, 2019, 2020 Google LLC. All Rights Reserved.
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at
 http://www.apache.org/licenses/LICENSE-2.0
 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
*/
// Incrementing OFFLINE_VERSION will kick off the install event and force
// previously cached resources to be updated from the network.
const OFFLINE_VERSION = 1
const CACHE_NAME = 'offline'
// Customize this with a different URL if needed.
const OFFLINE_URL = 'offline.html'
self.addEventListener('install', event => {
  event.waitUntil(
    (async () => {
      const cache = await caches.open(CACHE_NAME)
      // Setting {cache: 'reload'} in the new request will ensure that the
      // response isn't fulfilled from the HTTP cache; i.e., it will be from
      // the network.
      await cache.add(new Request(OFFLINE_URL, {cache: 'reload'}))
    })()
  )
  // Force the waiting service worker to become the active service worker.
  self.skipWaiting()
})
self.addEventListener('activate', event => {
  event.waitUntil(
    (async () => {
      // Enable navigation preload if it's supported.
      // See https://developers.google.com/web/updates/2017/02/navigation-preload
      if ('navigationPreload' in self.registration) {
        await self.registration.navigationPreload.enable()
      }
    })()
  )
  // Tell the active service worker to take control of the page immediately.
  self.clients.claim()
})
self.addEventListener('fetch', event => {
  // We only want to call event.respondWith() if this is a navigation request
  // for an HTML page.
  if (event.request.mode === 'navigate') {
    event.respondWith(
      (async () => {
        try {
          // First, try to use the navigation preload response if it's supported.
          const preloadResponse = await event.preloadResponse
          if (preloadResponse) {
            return preloadResponse
          }
          // Always try the network first.
          const networkResponse = await fetch(event.request)
          return networkResponse
        } catch (error) {
          // catch is only triggered if an exception is thrown, which is likely
          // due to a network error.
          // If fetch() returns a valid HTTP response with a response code in
          // the 4xx or 5xx range, the catch() will NOT be called.
          console.log('Fetch failed; returning offline page instead.', error)
          const cache = await caches.open(CACHE_NAME)
          const cachedResponse = await cache.match(OFFLINE_URL)
          return cachedResponse
        }
      })()
    )
  }
  // If our if() condition is false, then this fetch handler won't intercept the
  // request. If there are any other fetch handlers registered, they will get a
  // chance to call event.respondWith(). If no fetch handlers call
  // event.respondWith(), the request will be handled by the browser as if there
  // were no service worker involvement.
})

Также из основного образца сервис-воркера Google, вот что делает этот конкретный сервис-воркер:

  • Предварительно кэширует файлы HTML, JavaScript и CSS, необходимые для отображения этой страницы в автономном режиме. (Попробуйте, перезагрузив страницу без подключения к сети!)
  • Очищает ранее кэшированные записи при обновлении имени кэша.
  • Перехватывает сетевые запросы, возвращая кешированный ответ, если он доступен.
  • Если кешированного ответа нет, получает ответ из сети и добавляет его в кеш для использования в будущем.

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

Перейти в автономный режим

И последнее, что вам нужно сделать, это добавить автономный резервный HTML-файл. Сервисный работник кэширует этот файл и отображает его, когда пользователь не в сети. Этот пример очень простой, но вы можете многое сделать, чтобы предоставить пользователю автономную функциональность, которая может добавить значительную ценность вашему приложению.

В общей папке создайте файл с именем offline.html и вставьте в него следующий код:

<!DOCTYPE html>
<html lang="en">
  <head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, 
  initial-scale=1" />
  <title>You are offline</title>
  <style>
    body {
      font-family: helvetica, arial, sans-serif;
      margin: 2em;
    }
    h1 {
      font-style: italic;
      color: #209cee;
    }
    p {
    margin-block: 1rem;
    }
  </style>
  </head>
  <body>
    <h1>You are offline</h1>
  
    <p>Click the button below to try reloading.</p>
  
    <button type="button">⤾ Reload</button>
    <script>
      document.querySelector('button').addEventListener('click', ()    
      => {
      window.location.reload()
      })
    </script>
  </body>
</html>

Я адаптировал этот код отсюда: https://web.dev/offline-fallback-page/

Обратите внимание, как стили css и javascript включены в строку. Это потому, что вашему сервис-воркеру необходимо кэшировать все, что он будет использовать для автономного использования. Универсальный подход - это самый простой способ создать единую автономную страницу. Для того, чтобы сделать больше, вам нужно будет изменить сервис-воркер, чтобы он включал все ресурсы, которые вам нужны для работы в автономном режиме.

Установите свое приложение!

Если вы все сделали правильно, вы сможете запустить свое приложение на локальном хосте в Chrome и увидеть маленькую кнопку с плюсом внутри круга в конце строки поиска. Если вы нажмете на нее, вы должны получить приглашение установить приложение на свое устройство!

Ах, погрейтесь в лучах славы установленной PWA. Разве этот логотип не выглядит потрясающе на вашем рабочем столе ?!

Чтобы узнать, как сделать больше с вашим PWA, например создать кнопку в приложении, которая предлагает пользователю установить ваше приложение, я предлагаю проверить этот замечательный ресурс PWA. Https://web.dev/progressive-web-apps/

Примечание по использованию HTTPS

Для правильной работы вашего PWA необходимо использовать HTTPS. Чтобы узнать больше, просмотрите эти документы.

Спасибо за чтение и желаю вам удачного путешествия по PWA!