Skip to content

Практическая работа №10: Progressive Web App — Список покупок

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


Основные теоретические положения

Section titled “Основные теоретические положения”

Service Worker — это JavaScript-файл, который работает в фоновом режиме браузера, отдельно от основного потока выполнения веб-страницы. Он действует как программный прокси-сервер между браузером и сетью, позволяя перехватывать сетевые запросы, управлять кэшем и обеспечивать офлайн-функциональность. Service Worker не имеет прямого доступа к DOM, но может взаимодействовать со страницей через механизм обмена сообщениями (postMessage) и события [1].

Жизненный цикл Service Worker:

  1. Регистрация (Registration): Браузер скачивает и регистрирует файл Service Worker.
  2. Установка (Installation): Вызывается событие install. На этом этапе обычно происходит предварительное кэширование статических ресурсов.
  3. Активация (Activation): Вызывается событие activate. Здесь обычно происходит очистка старых кэшей.
  4. Работа (Fetch/Message): Service Worker готов перехватывать сетевые запросы (событие fetch) или получать сообщения.

IndexedDB — это встроенная в браузер низкоуровневая объектная база данных для хранения значительных объёмов структурированных данных на стороне клиента. В отличие от localStorage, IndexedDB [2]:

  • Поддерживает транзакции для обеспечения целостности данных.
  • Позволяет создавать индексы для быстрого поиска.
  • Работает асинхронно, не блокируя основной поток выполнения (UI).
  • Может хранить сложные объекты JavaScript.

Основные понятия IndexedDB:

  • База данных (Database): Контейнер для хранилищ объектов.
  • Хранилище объектов (Object Store): Аналог таблиц в реляционных БД.
  • Транзакция (Transaction): Оболочка вокруг операций чтения/записи.
  • Курсор (Cursor): Механизм для перебора записей в хранилище.

3. Стратегии кэширования

Section titled “3. Стратегии кэширования”

При перехвате запросов в Service Worker можно использовать различные стратегии [3]:

  • Cache First (Сначала кэш): Идеально для статических ресурсов (картинки, CSS, шрифты).
  • Network First (Сначала сеть): Подходит для часто обновляемых данных.
  • Stale While Revalidate (Устаревшее при обновлении): Немедленно возвращается кэш, а в фоне идет обновление.

Алгоритм выполнения работы

Section titled “Алгоритм выполнения работы”

Выполняйте задания последовательно. Для каждого пункта пишите код и проверяйте его работоспособность в браузере (используйте DevTools: вкладки Console, Application -> Service Workers, Application -> IndexedDB, Application -> Cache Storage).

Часть 1: Создание PWA и офлайн-режима

Section titled “Часть 1: Создание PWA и офлайн-режима”
  1. Подготовка проекта: Создайте папку pwa_shopping_list/ и базовые файлы: index.html, app.js, sw.js, styles.css, manifest.webmanifest, offline.html. Для разработки используйте локальный сервер (например, python3 -m http.server 8000).
  2. Создание Manifest: Заполните manifest.webmanifest (имя, иконки, start_url, display: standalone) и подключите его к index.html.
  3. Регистрация Service Worker: В app.js зарегистрируйте sw.js.
  4. Кэширование ресурсов: В sw.js на событие install создайте кэш shopping-list-cache-v1 и добавьте в него все основные файлы приложения, включая offline.html.
  5. Очистка старого кэша: На событие activate удалите все кэши, кроме shopping-list-cache-v1.
  6. Перехват запросов: На событие fetch реализуйте стратегию Cache First. При ошибке сети для навигационных запросов возвращайте страницу offline.html.
  7. Индикатор сети: В app.js добавьте слушатели online и offline для отображения статуса сети на странице.

Часть 2: Локальное хранение и работа со списком (IndexedDB)

Section titled “Часть 2: Локальное хранение и работа со списком (IndexedDB)”
  1. Инициализация БД: В app.js напишите функцию initDB(), которая открывает базу данных shopping_list_db версии 1.
  2. Создание хранилищ: В обработчике onupgradeneeded создайте два хранилища: items (keyPath: 'id', autoIncrement: true) и syncQueue (autoIncrement: true). В items создайте индекс по полю status.
  3. CRUD-операции: Реализуйте функции для работы с items:
    • addItem(item): добавляет товар.
    • getItems(): получает все товары.
    • updateItem(item): обновляет товар (используйте метод put).
    • deleteItem(id): удаляет товар.
  4. Тестовые данные: При первом открытии базы добавьте несколько тестовых товаров.

Часть 3: Интеграция интерфейса и расширенные возможности

Section titled “Часть 3: Интеграция интерфейса и расширенные возможности”
  1. Отображение данных: Напишите функцию renderItems(items), которая отрисовывает товары на странице. Каждый товар должен иметь название, чекбокс для отметки “Куплено”, кнопку “Редактировать” и кнопку “Удалить”.
  2. Редактирование товара: При нажатии на кнопку “Редактировать” позвольте пользователю изменить название товара (например, через prompt или заменив текст на input) и сохраните изменения с помощью updateItem().
  3. Поиск/фильтрация: Добавьте на страницу поле input для поиска. При вводе текста фильтруйте отображаемый список товаров в реальном времени.
  4. Массовые операции: Добавьте кнопки “Удалить купленные” и “Отметить все как купленные”, которые выполняют соответствующие действия над списком.
  5. Проверка офлайн-работы: Убедитесь, что все функции (добавление, редактирование, удаление, поиск) корректно работают в офлайн-режиме.

Часть 4: Имитация фоновой синхронизации (Background Sync)

Section titled “Часть 4: Имитация фоновой синхронизации (Background Sync)”
  1. Логика сохранения: Измените функцию добавления товара. Если navigator.onLine равно false, сохраняйте новый товар не только в items, но и в syncQueue.
  2. Синхронизация при появлении сети: В обработчике события online напишите логику, которая “отправляет” данные из syncQueue на сервер (имитируйте через console.log), а после “успешной отправки” очищает syncQueue.
  3. Индикатор: Добавьте на страницу счетчик “Ожидают синхронизации: N”, который показывает количество записей в syncQueue.

Часть 5: Администрирование и анализ

Section titled “Часть 5: Администрирование и анализ”
  1. Очистка данных: Добавьте кнопку “Очистить кэш и БД”, которая удаляет базу данных (indexedDB.deleteDatabase()) и все кэши в Cache Storage, после чего перезагружает страницу.
  2. Анализ производительности: Подготовьте краткий отчёт (в виде Markdown-файла report.md) о том, как Service Worker влияет на скорость повторной загрузки приложения. Сравните время загрузки с включенным и отключенным SW через вкладку Network в DevTools (показатели DOMContentLoaded и Finish).

  1. Что такое Progressive Web App (PWA) и какие его основные преимущества?
  2. Что такое Service Worker и чем он отличается от обычного JavaScript-кода на странице?
  3. Какие события жизненного цикла Service Worker вы использовали и зачем они нужны?
  4. Что такое Cache Storage и как он помогает обеспечить офлайн-доступ к приложению?
  5. Чем стратегия Cache First отличается от Network First? В каких случаях какую лучше применять?
  6. Что такое manifest.webmanifest и для чего он используется в PWA?
  7. Что такое IndexedDB и чем она отличается от localStorage и sessionStorage?
  8. Как создаётся объектное хранилище в IndexedDB? Что такое keyPath и autoIncrement?
  9. Зачем нужны транзакции в IndexedDB? Какие режимы транзакций существуют?
  10. Как работает механизм имитации синхронизации данных, реализованный в Части 4, и почему он важен для офлайн-приложений?

Рекомендуемая литература и ресурсы

Section titled “Рекомендуемая литература и ресурсы”
  1. MDN Web Docs: Service Worker API
  2. MDN Web Docs: Использование IndexedDB
  3. web.dev: Service workers and the Cache Storage API
  4. JavaScript.info: IndexedDB
  5. Google Developers: The Offline Cookbook (Стратегии кэширования)
  6. MDN Web Docs: Web App Manifest