Быстрый запуск в автономном режиме

Эта лаборатория кода является частью учебного курса "Разработка прогрессивных веб-приложений", разработанного командой Google Developers Training. Вы получите максимальную отдачу от этого курса, если будете последовательно работать с кодлабами.

Полную информацию о курсе см . в обзоре «Разработка прогрессивных веб-приложений» .

Введение

В этом лабораторном занятии вы будете использовать Lighthouse для проверки веб-сайта на соответствие стандартам Progressive Web App (PWA). Вы также добавите автономную функциональность с помощью Service Worker API.

Что вы узнаете

  • Как проводить аудит сайтов с Lighthouse
  • Как добавить автономные возможности в приложение

То, что вы должны знать

  • Базовый HTML, CSS и JavaScript
  • Знакомство с промисами ES2015

Что тебе понадобится

  • Компьютер с доступом к терминалу/оболочке
  • Подключение к Интернету
  • Браузер Chrome (для использования Lighthouse)
  • Текстовый редактор
  • Необязательно: Chrome на устройстве Android

Загрузите или клонируйте репозиторий pwa-training-labs с github и при необходимости установите LTS-версию Node.js.

Перейдите в каталог offline-quickstart-lab/app/ и запустите локальный сервер разработки:

cd offline-quickstart-lab/app
npm install
node server.js

Вы можете остановить сервер в любое время с помощью Ctrl-c .

Откройте браузер и перейдите на localhost:8081/ . Вы должны увидеть, что сайт представляет собой простую и статическую веб-страницу.

Примечание. Отмените регистрацию всех сервис-воркеров и очистите все кэши сервис-воркеров для локального хоста, чтобы они не мешали работе лаборатории. В Chrome DevTools это можно сделать, нажав « Очистить данные сайта » в разделе « Очистить хранилище » на вкладке « Приложение ».

Откройте папку offline-quickstart-lab/app/ в предпочитаемом вами текстовом редакторе. Папка app/ — это место, где вы будете создавать лабораторию.

Эта папка содержит:

  • images/ папка содержит образцы изображений
  • styles/main.css — основная таблица стилей.
  • index.html — это главная HTML-страница нашего тестового сайта.
  • package-lock.json и package.json отслеживают зависимости приложения (единственные зависимости в этом случае относятся к локальному серверу разработки)
  • server.js — локальный сервер разработки для тестирования
  • service-worker.js — файл сервисного работника (в настоящее время пустой)

Прежде чем мы начнем вносить изменения в сайт, давайте проведем аудит с помощью Lighthouse , чтобы увидеть, что можно улучшить.

Вернитесь в приложение (в Chrome) и откройте вкладку « Аудит » инструментов разработчика . Вы должны увидеть значок Lighthouse и параметры конфигурации. Выберите «Мобильное» для « Устройство », выберите «Все аудиты », выберите любой из параметров « Дросселирование » и выберите « Очистить хранилище »:

Щелкните Провести аудит . Аудит занимает несколько минут.

Объяснение

После завершения аудита вы должны увидеть отчет с оценками в инструментах разработчика. Он должен показывать баллы, что-то вроде этого (баллы могут не совпадать):

Примечание. Оценки Lighthouse являются приблизительными и могут зависеть от вашей среды (например, если у вас открыто большое количество окон браузера). Ваши баллы могут не совпадать с показанными здесь.

И раздел Progressive Web App должен выглядеть примерно так:

Отчет содержит оценки и показатели в пяти категориях:

  • Прогрессивное веб-приложение
  • Производительность
  • Доступность
  • Лучшие практики
  • SEO

Как видите, наше приложение имеет низкие оценки в категории Progressive Web App (PWA). Давайте улучшим наш счет!

Найдите минутку, чтобы просмотреть раздел отчета PWA и увидеть, чего не хватает.

Зарегистрировать сервисного работника

Одна из ошибок, перечисленных в отчете, заключается в том, что ни один сервис-воркер не зарегистрирован. В настоящее время у нас есть пустой файл сервис-воркера по адресу app/service-worker.js .

Добавьте следующий скрипт в index.html непосредственно перед закрывающим </body> :

<script>
if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('service-worker.js')
      .then(reg => {
        console.log('Service worker registered! 😎', reg);
      })
      .catch(err => {
        console.log('😥 Service worker registration failed: ', err);
      });
  });
}
</script>

Объяснение

Этот код регистрирует пустой рабочий файл службы sw.js после загрузки страницы. Однако текущий файл сервисного работника пуст и ничего не делает. Давайте добавим сервисный код на следующем шаге.

Ресурсы предварительного кэширования

Еще одна ошибка, указанная в отчете, заключается в том, что приложение не отвечает кодом состояния 200 в автономном режиме. Нам нужно обновить наш сервис-воркер, чтобы решить эту проблему.

Добавьте следующий код в файл сервис-воркера ( sw.js ):

const cacheName = 'cache-v1';
const precacheResources = [
  '/',
  'index.html',
  'styles/main.css',
  'images/space1.jpg',
  'images/space2.jpg',
  'images/space3.jpg'
];

self.addEventListener('install', event => {
  console.log('Service worker install event!');
  event.waitUntil(
    caches.open(cacheName)
      .then(cache => {
        return cache.addAll(precacheResources);
      })
  );
});

self.addEventListener('activate', event => {
  console.log('Service worker activate event!');
});

self.addEventListener('fetch', event => {
  console.log('Fetch intercepted for:', event.request.url);
  event.respondWith(caches.match(event.request)
    .then(cachedResponse => {
        if (cachedResponse) {
          return cachedResponse;
        }
        return fetch(event.request);
      })
    );
});

Теперь вернитесь в браузер и обновите сайт. Проверьте консоль, чтобы увидеть, что сервис-воркер:

  • зарегистрирован
  • установлены
  • активирован

Примечание. Если вы уже зарегистрировали сервис-воркер ранее или у вас возникли проблемы с запуском всех событий, отмените регистрацию всех сервис-воркеров и обновите страницу. Если это не удается, закройте все экземпляры приложения и снова откройте его.

Затем завершите локальный сервер разработки в командной строке, запустив Ctrl + c . Обновите сайт еще раз и обратите внимание, что он загружается, даже если сервер отключен!

Примечание. Вы можете увидеть ошибку консоли, указывающую на то, что сервисный работник не может быть получен: An unknown error occurred when fetching the script. service-worker.js Failed to load resource: net::ERR_CONNECTION_REFUSED . Эта ошибка появляется из-за того, что браузеру не удалось загрузить скрипт сервис-воркера (поскольку сайт отключен), но это ожидаемо, потому что мы не можем использовать сервис-воркер для кэширования самого себя. В противном случае браузер пользователя застрял бы с одним и тем же сервис-воркером навсегда!

Объяснение

Как только сервис-воркер зарегистрирован сценарием регистрации в index.html , происходит событие install сервис-воркера. Во время этого события прослушиватель событий install открывает именованный кэш и кэширует файлы, указанные с помощью метода cache.addAll . Это называется предварительным кэшированием, поскольку происходит во время install , которая обычно происходит при первом посещении сайта пользователем.

После установки сервис-воркера и если другой сервис-воркер в данный момент не контролирует страницу, новый сервис-воркер «активируется» (в сервис-воркере запускается прослушиватель событий activate ), и он начинает управлять страницей.

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

Кэширование ресурсов позволяет приложению работать в автономном режиме, избегая сетевых запросов. Теперь наше приложение может отвечать кодом состояния 200 в автономном режиме!

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

Необязательно : вы также можете увидеть кэшированные ресурсы на вкладке « Приложение » инструментов разработчика, развернув раздел « Хранилище кэша »:

Перезапустите сервер разработки с node server.js и обновите сайт. Затем снова откройте вкладку « Аудит » в инструментах разработчика и повторно запустите аудит Lighthouse, выбрав « Новый аудит » (знак «плюс» в верхнем левом углу). Когда аудит будет завершен, вы должны увидеть, что наша оценка PWA значительно лучше, но ее еще можно улучшить. Мы продолжим улучшать нашу оценку в следующем разделе.

Примечание. Этот раздел является необязательным, поскольку тестирование баннера установки веб-приложения выходит за рамки лабораторной работы. Вы можете попробовать это самостоятельно, используя удаленную отладку .

Наша оценка PWA по-прежнему невелика. Некоторые из оставшихся сбоев, перечисленных в отчете, заключаются в том, что пользователю не будет предложено установить наше веб-приложение, и что мы не настроили заставку или фирменные цвета в адресной строке. Мы можем решить эти проблемы и постепенно внедрять функцию « Добавить на главный экран », удовлетворяя некоторым дополнительным критериям . Самое главное, нам нужно создать файл манифеста .

Создайте файл манифеста

Создайте файл в app/ с именем manifest.json и добавьте следующий код:

{
  "name": "Space Missions",
  "short_name": "Space Missions",
  "lang": "en-US",
  "start_url": "/index.html",
  "display": "standalone",
  "theme_color": "#FF9800",
  "background_color": "#FF9800",
  "icons": [
    {
      "src": "images/touch/icon-128x128.png",
      "sizes": "128x128"
    },
    {
      "src": "images/touch/icon-192x192.png",
      "sizes": "192x192"
    },
    {
      "src": "images/touch/icon-256x256.png",
      "sizes": "256x256"
    },
    {
      "src": "images/touch/icon-384x384.png",
      "sizes": "384x384"
    },
    {
      "src": "images/touch/icon-512x512.png",
      "sizes": "512x512"
    }
  ]
}

Изображения, указанные в манифесте, уже предоставлены в приложении.

Затем добавьте следующий HTML-код в конец тега <head> в index.html :

<link rel="manifest" href="manifest.json">

<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="application-name" content="Space Missions">
<meta name="apple-mobile-web-app-title" content="Space Missions">
<meta name="theme-color" content="#FF9800">
<meta name="msapplication-navbutton-color" content="#FF9800">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="msapplication-starturl" content="/index.html">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

<link rel="icon" sizes="128x128" href="/images/touch/icon-128x128.png">
<link rel="apple-touch-icon" sizes="128x128" href="/images/touch/icon-128x128.png">
<link rel="icon" sizes="192x192" href="icon-192x192.png">
<link rel="apple-touch-icon" sizes="192x192" href="/images/touch/icon-192x192.png">
<link rel="icon" sizes="256x256" href="/images/touch/icon-256x256.png">
<link rel="apple-touch-icon" sizes="256x256" href="/images/touch/icon-256x256.png">
<link rel="icon" sizes="384x384" href="/images/touch/icon-384x384.png">
<link rel="apple-touch-icon" sizes="384x384" href="/images/touch/icon-384x384.png">
<link rel="icon" sizes="512x512" href="/images/touch/icon-512x512.png">
<link rel="apple-touch-icon" sizes="512x512" href="/images/touch/icon-512x512.png">

Вернуться на сайт. На вкладке « Приложение » инструментов разработчика выберите раздел « Очистить хранилище » и нажмите « Очистить данные сайта ». Затем обновите страницу. Теперь выберите раздел « Манифест ». Вы должны увидеть значки и параметры конфигурации, настроенные в файле manifest.json . Если вы не видите своих изменений, откройте сайт в режиме инкогнито и проверьте еще раз.

Объяснение

Файл manifest.json сообщает браузеру, как стилизовать и форматировать некоторые прогрессивные аспекты вашего приложения, такие как хром браузера, значок главного экрана и экран-заставка. Его также можно использовать для настройки вашего веб-приложения для открытия в standalone режиме, как это делает собственное приложение (другими словами, вне браузера).

На момент написания этой статьи поддержка для некоторых браузеров все еще находится в стадии разработки, и теги <meta> настраивают подмножество этих функций для определенных браузеров, которые еще не имеют полной поддержки.

Нам пришлось очистить данные сайта, чтобы удалить нашу старую кешированную версию index.html (поскольку в этой версии не было ссылки на манифест). Попробуйте провести еще один аудит Lighthouse и посмотрите, насколько улучшилась оценка PWA!

Активация запроса на установку

Следующим шагом к установке нашего приложения является отображение пользователям запроса на установку. Chrome 67 предлагал пользователям автоматически, но, начиная с Chrome 68 , запрос на установку должен активироваться программно в ответ на жест пользователя.

Добавьте кнопку «Установить приложение» и баннер вверху index.html (сразу после <main> ) с помощью следующего кода:

<section id="installBanner" class="banner">
    <button id="installBtn">Install app</button>
</section>

Затем стилизуйте баннер, добавив следующие стили в styles/main.css :

.banner {
  align-content: center;
  display: none;
  justify-content: center;
  width: 100%;
}

Сохраните файл. Наконец, добавьте следующий тег скрипта в index.html :

  <script>
    let deferredPrompt;
    window.addEventListener('beforeinstallprompt', event => {

      // Prevent Chrome 67 and earlier from automatically showing the prompt
      event.preventDefault();

      // Stash the event so it can be triggered later.
      deferredPrompt = event;

      // Attach the install prompt to a user gesture
      document.querySelector('#installBtn').addEventListener('click', event => {

        // Show the prompt
        deferredPrompt.prompt();

        // Wait for the user to respond to the prompt
        deferredPrompt.userChoice
          .then((choiceResult) => {
            if (choiceResult.outcome === 'accepted') {
              console.log('User accepted the A2HS prompt');
            } else {
              console.log('User dismissed the A2HS prompt');
            }
            deferredPrompt = null;
          });
      });

      // Update UI notify the user they can add to home screen
      document.querySelector('#installBanner').style.display = 'flex';
    });
  </script>

Сохраните файл. Откройте приложение в Chrome на устройстве Android с помощью удаленной отладки . Когда страница загрузится, вы должны увидеть кнопку «Установить приложение» (вы не увидите ее на рабочем столе, поэтому убедитесь, что вы тестируете на мобильном устройстве). Нажмите кнопку, и появится приглашение «Добавить на главный экран». Следуйте инструкциям, чтобы установить приложение на свое устройство. После установки вы сможете открыть веб-приложение в автономном режиме (вне браузера), коснувшись только что созданного значка на главном экране.

Объяснение

Код HTML и CSS добавляет скрытый баннер и кнопку, которые мы можем использовать, чтобы позволить пользователям активировать запрос на установку.

Как только срабатывает событие beforeinstallprompt , мы предотвращаем работу по умолчанию (в которой Chrome 67 и более ранние версии автоматически предлагают пользователям установить) и beforeinstallevent в глобальной переменной deferredPrompt . Затем кнопка «Установить приложение» настраивается для отображения подсказки с помощью beforeinstallevent prompt() перед установкой события. Как только пользователь делает выбор (устанавливать или нет), обещание userChoice разрешается выбором пользователя ( outcome ). Наконец, мы отображаем кнопку установки, как только все будет готово.

Вы узнали, как проводить аудит сайтов с помощью Lighthouse и как реализовать основы автономной работы. Если вы заполнили дополнительные разделы, вы также узнали, как устанавливать веб-приложения на главный экран!

Дополнительные ресурсы

Маяк с открытым исходным кодом! Вы можете разветвить его, добавить свои собственные тесты и файлы ошибок. Lighthouse также доступен как инструмент командной строки для интеграции с процессами сборки.

Чтобы увидеть все кодовые лаборатории в учебном курсе PWA, см. приветственную лабораторную работу для курса/