Рубріки: Теория

PWA (Progressive Web App) – что это такое и в чем его особенности

Сергій Бондаренко

В этом материале мы поговорим о относительно молодой технологии — Progressive Web App (PWA).

Что такое PWA

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

История развития Progressive Web App

История Progressive Web Apps (PWA) началась с появлением в 2007 году первых HTML5 API, когда стало возможным создавать многофункциональные интерактивные веб-приложения. До этого веб-приложения не могли работать в автономном режиме, не имели доступа к аппаратному обеспечению устройства и поэтому отставали от нативных приложений.

В 2015 году компания Google начала работать над концепцией PWA и предложила новые API и инструменты для создания веб-приложений, которые могли работать как нативные приложения. В частности, было предложено использование Service Workers — специальных скриптов, которые позволяют создавать офлайн-сервисы и кэшировать данные.

Service Worker — это как бы промежуточный слой между веб-приложением и сервером, который может кэшировать запросы (а также ответы на них), чтобы приложение могло быстро работать без доступа к Интернету. Это значительно ускоряет загрузку страниц и уменьшает нагрузку на сервер.

Кроме того, Google предложил использовать Web App Manifest — JSON-файл, который описывает основные параметры приложения, такие как название, значок, цветовую схему и другие характеристики, которые обычно ассоциируются с нативными приложениями.

Web App Manifest дает возможность установить PWA на главный экран устройства и создать более реалистичный интерфейс пользователя, похожий на native.

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

Но самым важным шагом в развитии веб-технологий и в поддержке прогрессивных веб-приложений стал выпуск мобильной версии соцсети Twitter в 2017 году. Это приложение использовало новые API и инструменты, предложенные Google, и давало возможность участника сети использовать Twitter в автономном режиме, получать уведомления. Также оно имело доступ к камере и некоторым другим аппаратным ресурсам устройства.

Особенности внедрения PWA и его архитектура

В зависимости от того, какой подход разработчики решили использовать для проектирования PWA-приложения, оно может быть как SPA (Single-Page Application), так и MPA (Multi-Page Application) — это не принципиально.

Архитектура PWA основывается на стандартных веб-технологиях, таких как HTML, CSS и JavaScript, и имеет три основных компонента:

  • клиентскую сторону (frontend);
  • серверную сторону (backend);
  • манифест приложения (manifest).

Клиентская сторона — это фронтенд-часть приложения, которая работает на стороне клиента (то есть в браузере). Она написана на HTML, CSS и JavaScript и отвечает за визуальное представление приложения и формирует пользовательский интерфейс, с определенной логикой взаимодействия с пользователем. Клиентская сторона PWA может быть написана с использованием любых фреймворков и библиотек, таких как React, Vue, Angular и др. 

Чтобы научиться создавать прогрессивные веб-приложения, надо сначала освоить верстку и фронтенд. Получить знания по HTML, CSS вы можете на курсе школы Hillel Front-end Basic, в потом продолжить изучать JavaScript на курсе Front-end Pro.

Серверная сторона — это бэкэнд-часть приложения, которая отвечает за обработку запросов и предоставление данных для клиентской стороны. В PWA серверная сторона может быть создана на любом языке программирования, например, PHP, Node.js, Python и других. 

Вот как это работает:

  1. При запуске PWA сначала загружается HTML, CSS и JavaScript-код.
  2. Затем запускается Service Worker, фоновый процесс, который работает в браузере, отвечает за кэширование контента и управление офлайн-режимом и может использоваться для предварительной загрузки ресурсов и кэширования данных. При этом кэшированные ресурсы могут быть использованы без подключения к Интернету.
  3. Для хранения данных используется объектно-ориентированное хранилище IndexedDB, где можно хранить структурированные данные, включая объекты JavaScript.  Процесс сохранения структурированных данных запускается отдельным потоком, что обеспечивает его отделение от основного потока веб-страницы, и позволяет работать независимо от состояния страницы или приложения.

Изучай Python на курсах от Mate Academy, или приходи сразу на Fullstack программу, где ты овладеешь и фронтенд, и бэкэнд за 4 месяца. Учиться можно бесплатно и оплатить курсы уже после трудоустройства.

Манифест приложения — это JSON-файл, который включает в себя метаданные приложения (имя, иконку, описание, цветовую схему и прочие настройки). Файл manifest содержит ссылки на другие ресурсы, такие как файлы скриптов, которые также загружаются при запуске PWA. Содержимое этого файла анализируется браузером в процессе установки PWA-приложения.

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

Еще одно требование к архитектуре progressive-приложений — поддержка HTTPS. PWA должно работать по протоколу HTTPS, чтобы обеспечить безопасную передачу данных между клиентом и сервером. HTTPS также необходим для использования Service Worker и доступа к некоторым API браузера, таким как, например, API геолокации.

PWA в ecommerce и преимущества архитектуры

PWA получили широкое распространение, и многие крупные компании (Uber, Pinterest, Starbucks и другие) начали создавать свои PWA-приложения. Особенно популярны PWA стали среди компаний, которые желают предоставить пользователям легкий и быстрый доступ к своим сервисам без необходимости устанавливать приложения из AppStore.

Для решения задач, связанных с ведением онлайн бизнеса progressive-приложение — отличный выбор.

Можно найти немало аргументов в пользу этой архитектуры: 

  • PWA могут повысить конверсию сайта. Поскольку пользователи быстро получают доступ к функциям, например, магазина, это увеличивает вероятность того, что клиент выполнит желаемое действие — совершит покупку, сделает заказ услуги и т.д.
  • Использование PWA означает снижение затрат на разработку. PWA задействуют одинаковый код для работы на разных платформах, поэтому их создание может быть более экономичным, чем мобильная разработка для каждой платформы отдельно.
  • Упрощается процедура внесения обновлений — пользователь не должен постоянно обновлять приложение через магазин приложений. Кроме того, у прогрессивных приложений быстрый отклик и скорость работы за счет кэширования.
  • Благодаря своей независимости от платформы, PWA может работать на любых устройствах, включая iOS и Android. Это помогает достичь максимальный охват аудитории, что особенно важно для магазинов, которые хотят расширить свой бизнес на новые рынки.

Недостатки PWA и как с ними бороться

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

  1. Технология не универсальна— она может не поддерживаться некоторыми браузерами. Хотя в большинстве современных браузеров с совместимостью проблем не наблюдается, отдельные устаревшие версии могут оказаться «за бортом». Решение проблемы: использовать свежии версии браузеров.
  2. PWA постоянно записывает данные в кэш и обращается к нему в офлайн-режиме по мере надобности. Это удобная фича, но по этой же причине технология дополнительно расходует память. Эта проблема решается комплексным подходом и постоянной оптимизацией:
    (1) Применяйте «ленивую загрузку ресурсов». Это означает, что ресурсы (изображения, скрипты и стили) загружаются только тогда, когда они действительно нужны.
    (2) Сжимайте данные, чтобы сократить трафик. Обязательно проводим оптимизацию изображений.
    (3) Сведите к минимуму число сторонних фреймворков и библиотек, а само приложение тщательно тестируйте на предмет утечек памяти. Приложение должно регулярно удалять неиспользуемые объекты и данные для освобождения памяти.
  3. Опять же, по причине кэширования файлов и данных для офлайн-режима, PWA-приложение может занимать больше места в устройстве по сравнению с обычным веб-приложением. Здесь остается только делать выбор в пользу экономии памяти/разработки PWA.
  4. Если PWA-приложения настроены некорректно, они могут вызывать проблемы с SEO-оптимизацией. Дело в том, что PWA-приложения могут использовать динамическое содержимое, которое генерируется на стороне клиента, и этот контент может быть сложным для индексации поисковыми роботами.
    Для борьбы с этой проблемой есть ряд уловок:
    (1) применять предварительный рендеринг (prerendering) для создания статических HTML-страниц, которые поисковые роботы смогут легко проиндексировать;
    (2) использовать тег meta для указания правильных метаданных, таких как title, description и keywords, которые позволят поисковым роботам правильно индексировать страницы приложения.
    Кроме того, PWA-приложения могут иметь свой собственный URL-адрес — это тоже помогает индексированию страниц в поисковых системах. Для этого нужно настроить соответствующие маршрутизаторы, которые подскажут поисковым ботам, как правильно индексировать страницы приложения.

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

Пример простейшего PWA-приложения

Давайте напишем простейшее PWA-приложение, на примере которого станет понятно, как функционирует эта архитектура.

Нам понадобятся четыре файла:

  • index.html — в нем будет прописана структура Web App Shell, основа PWA. В контексте PWA index.html работает как точка входа в приложение, которую открывает пользователь при запуске приложения или при переходе на него из списка приложений на устройстве. Здесь мы определяем навигационную панель, основной контент и другие элементы пользовательского интерфейса.
  • script.js — тут может быть любой код, связанный с функциональностью вашего приложения. Например, это может быть код для получения и обработки данных, код для работы с пользовательским интерфейсом, обработка событий и так далее. Код, который вы напишете, будет зависеть от того, что именно должно делать ваше приложение.
  • style.css — файл со стилями для HTML-страницы.
  • sw.js — файл JavaScript, который содержит код Service Worker для вашего веб-приложения. Код будет работать в фоновом режиме и может перехватывать запросы к серверной части, кэшировать ресурсы, обрабатывать push-уведомления и многое другое. В файле sw.js вы можете определять, какие запросы кэшировать, как обрабатывать события жизненного цикла и т.д. Обычно код для регистрации Service Worker размещается в обработчике события load, чтобы гарантировать, что все ресурсы страницы загрузились до запуска регистрации Service Worker.

Файл sw.js не нужно подключать в разметке HTML-файла. Он подключается в JavaScript-файле, который обрабатывает регистрацию Service Worker, например, внутри файла script.js.

Код нашего макета веб-приложения будет выглядеть очень просто:

<!DOCTYPE html>

<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>My PWA</title>
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <h1>My PWA</h1>
    <p>This is a simple PWA example for Highload.today.</p>
    <button class="btn">Click me!</button>
    <script src="script.js"></script>
  </body>
</html>

Файл со стилями:

body {
    margin: 0;
    padding: 0;
    font-family: sans-serif;
  }
  header {
    background-color: #333;
    color: #fff;
    padding: 20px;
  }
  h1 {
    margin: 0;
  }
  main {
    padding: 20px;
  }
  .btn {
    background-color: #4CAF50;
    color: white;
    padding: 12px 24px;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 16px;
  }
  .btn:hover {
    background-color: #3e8e41;
  }

Файл script.js:

const button = document.querySelector('.btn');
button.addEventListener('click', () => {
  button.disabled = true;
  button.textContent = 'Loading...';
  console.log('Button clicked');
  fetch('https://jsonplaceholder.typicode.com/posts')
    .then(response => response.json())
    .then(data => {
      console.log('Data loaded', data);
      setTimeout(() => {
        button.disabled = false;
        button.textContent = 'Click me!';
      }, 2000); // задержка в 2 секунды
    })
    .catch(error => {
      console.error('Error:', error);
      setTimeout(() => {
        button.disabled = false;
        button.textContent = 'Click me!';
      }, 2000); // задержка в 2 секунды
    });
});

if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('/sw.js').then(function(registration) {
      console.log('ServiceWorker registration successful with scope: ', registration.scope);
    }, function(err) {
      console.log('ServiceWorker registration failed: ', err);
    });
  });
}

Теперь напишем код для файла sw.js — он регистрирует сервисный рабочий скрипт и кэширует необходимые ресурсы.

Также код обрабатывает события fetch, что позволяет использовать кэшированные ресурсы во время выполнения запросов. Но при работе с кэшем может возникнуть неожиданное поведение, поэтому важно тестировать и отлаживать этот функционал:

var CACHE_NAME = 'my-pwa-cache-v1';
// Проводим кэширование необходимых ресурсов в момент установки Service Worker
self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(function(cache) {
        return cache.addAll([
          '/',
          '/index.html',
          '/style.css',
          '/script.js'
        ]);
      })
  );
});

// Кэширование запросов
self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.match(event.request)
      .then(function(response) {
        // Если ресурс найден в кэше, возвращаем его из кэша
        if (response) {
          return response;
        }
        // Если ресурс отсутствует в кэше, запрашиваем его с сервера и сохраняем ответ в кэше
        return fetch(event.request)
          .then(function(response) {
            // Проверяем, что ответ корректный, иначе возвращаем его не кэшируя
            if(!response || response.status !== 200 || response.type !== 'basic') {
              return response;
            }
            // кэшируем успешный ответ и возвращаем его
            var responseToCache = response.clone();
            caches.open(CACHE_NAME)
              .then(function(cache) {
                cache.put(event.request, responseToCache);
              });
            return response;
          });
      })
  );
});

// Избавление от устаревших кэшей при активировании нового Service Worker
self.addEventListener('activate', function(event) {
  var cacheWhitelist = ['my-pwa-cache-v1'];
  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        cacheNames.map(function(cacheName) {
          if (cacheWhitelist.indexOf(cacheName) === -1) {
            return caches.delete(cacheName);
          }
        })
      );
    })
  );
});

Первая часть кода, запускающаяся при установке Service Worker, инициализирует кэш и кэширует основные ресурсы приложения (index.html, style.css, script.js).

Вторая часть кода, запускающаяся при выполнении запроса, проверяет наличие запрашиваемого ресурса в кэше:

  • если ресурс найден, он возвращается из кэша;
  • если же ресурс не найден, происходит запрос на сервер и результат кэшируется.

В случае некорректного серверного ответа (не 200 или не тип basic), ответ возвращается без кэширования.

И, наконец, третья часть кода отвечает за удаление устаревших кэшей при активации нового Service Worker.

Запустим наше приложение и посмотрим, что происходит.

Для запуска приложения нужно запустить локальный веб-сервер. Самый простой способ сделать это — с помощью расширения для браузера, например, Web Server for Chrome из Chrome Web Store.

Если вы предпочитаете не использовать расширение для браузера, вы можете запустить локальный сервер из командной строки, используя такие инструменты, как Node.js, PHP, Python или любой другой серверный язык программирования. Недостаточно знаете Python? Попробуйте курс от Powercode Academy.

Например:

  • устанавливаете Node.js;
  • затем открываете терминал и пишете npm install -g http-server;
  • переходите в каталог с проектом cd/path/to/project и выполняете команду http-server;
  • после этого запускаете браузер и переходите по адресу http://localhost:8080 (или другому порту, если он был указан в команде запуска).

Если все сделано правильно, вы увидите содержимое вашего проекта в браузере.

Наше приложение — это простое PWA (Progressive Web App), которое позволяет загрузить список постов (posts) с помощью API, предоставляемого сервисом JSONPlaceholder.

Для этой цели в приложении есть кнопка Click me!, которая загружает список постов, используя JavaScript Fetch API:

  • при нажатии на кнопку она становится неактивной и меняет свой текст на “Loading…” (стоит двухсекундная задержка), чтобы пользователь знал, что происходит загрузка данных;
  • далее запускается функция fetch(), которая отправляет GET-запрос на сервер по указанному адресу “https://jsonplaceholder.typicode.com/posts“;
  • когда сервер возвращает ответ, его содержимое преобразуется из формата JSON в JavaScript-объект при помощи метода .json(), который вызывается на объекте Response, полученном из сервера;
  • полученные данные выводятся в консоль для проверки.

После получения данных кнопка становится снова активной и возвращается ее первоначальный текст “Click me!”:

В этом конкретном примере мы не писали код для манифеста. Но обычно файл манифеста должен быть создан в корневом каталоге приложения и называться manifest.json. В этом файле должна быть определена информация о приложении, такая как название, описание, иконки, цвета и другие параметры.

Проследить за процессом кэширования и функционированием приложения можно через инструменты разработчика:

Заключение

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

Если суммировать вкратце, то PWA — мощная и интересная технология, которая при этом требует комплексного подхода к управлению памятью и SEO-оптимизации.

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

В заключение мы рекомендуем вам посмотреть видео, в котором рассказывается, как просто и быстро преобразовать существующее веб-приложение в PWA:

Хочешь создавать прогрессивные веб-приложения сам? Твой выбор — Fullstack курсы от Mate Academy. Можешь учиться полный день и платить после трудоустройства или выбрать вечерние курсы с гибким графиком.

Останні статті

Обучение Power BI – какие онлайн курсы аналитики выбрать

Сегодня мы поговорим о том, как выбрать лучшие курсы Power BI в Украине, особенно для…

13.01.2024

Work.ua назвал самые конкурентные вакансии в IТ за 2023 год

В 2023 году во всех крупнейших регионах конкуренция за вакансию выросла на 5–12%. Не исключением…

08.12.2023

Украинская IT-рекрутерка создала бесплатный трекер поиска работы

Unicorn Hunter/Talent Manager Лина Калиш создала бесплатный трекер поиска работы в Notion, систематизирующий все этапы…

07.12.2023

Mate academy отправит работников в 10-дневный оплачиваемый отпуск

Edtech-стартап Mate academy принял решение отправить своих работников в десятидневный отпуск – с 25 декабря…

07.12.2023

Переписки, фото, история браузера: киевский программист зарабатывал на шпионаже

Служба безопасности Украины задержала в Киеве 46-летнего программиста, который за деньги устанавливал шпионские программы и…

07.12.2023

Как вырасти до сеньйора? Девелопер создал популярную подборку на Github

IT-специалист Джордан Катлер создал и выложил на Github подборку разнообразных ресурсов, которые помогут достичь уровня…

07.12.2023