Offline режим

Offline-режим в приложениях на базе Quasar строится вокруг концепции прогрессивных веб-приложений (PWA) и использования Service Worker. Основная задача — обеспечить корректную работу интерфейса и логики при отсутствии сетевого соединения, а также синхронизацию данных при восстановлении связи.

Ключевые составляющие:

  • Service Worker — перехватывает сетевые запросы и управляет кэшированием
  • Cache Storage API — хранит статические и динамические ресурсы
  • IndexedDB / LocalStorage — используется для хранения пользовательских данных
  • Network detection — отслеживание состояния соединения

Quasar предоставляет встроенную поддержку PWA через режим pwa, который активируется в конфигурации проекта.


Настройка PWA режима

Для включения offline-возможностей необходимо активировать PWA режим:

quasar mode add pwa

После этого в проекте появляются:

  • папка src-pwa/
  • файл register-service-worker.js
  • конфигурация в quasar.config.js

В конфигурации задаются параметры Service Worker:

pwa: {
  workboxMode: 'GenerateSW', // или 'InjectManifest'
  workboxOptions: {
    skipWaiting: true,
    clientsClaim: true
  }
}

Режимы работы:

  • GenerateSW — автоматическая генерация Service Worker
  • InjectManifest — ручное управление логикой Service Worker

Для сложных offline-сценариев предпочтителен InjectManifest.


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

Service Worker использует различные стратегии кэширования:

Cache First

Сначала проверяется кэш, затем сеть:

workbox.routing.registerRoute(
  ({ request }) => request.destination === 'image',
  new workbox.strategies.CacheFirst()
)

Используется для:

  • изображений
  • шрифтов
  • статических ресурсов

Network First

Сначала сеть, при ошибке — кэш:

new workbox.strategies.NetworkFirst()

Подходит для:

  • API-запросов
  • динамического контента

Stale While Revalidate

Быстрый ответ из кэша с обновлением в фоне:

new workbox.strategies.StaleWhileRevalidate()

Баланс между скоростью и актуальностью.


Работа с Service Worker в Quasar

Файл src-pwa/custom-service-worker.js (при InjectManifest) позволяет управлять логикой:

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(response => {
      return response || fetch(event.request)
    })
  )
})

Также можно реализовать:

  • fallback-страницы
  • обработку ошибок сети
  • кастомные стратегии

Детекция состояния сети

Quasar предоставляет плагин Network:

import { Network } from 'quasar'

if (Network.isOnline) {
  console.log('Online')
} else {
  console.log('Offline')
}

Отслеживание изменений:

window.addEventListener('online', () => {
  console.log('Соединение восстановлено')
})

window.addEventListener('offline', () => {
  console.log('Соединение потеряно')
})

Это позволяет:

  • отображать уведомления
  • блокировать действия
  • запускать синхронизацию

Хранение данных офлайн

Для хранения данных используются:

LocalStorage

Простой API:

localStorage.setItem('key', JSON.stringify(data))

Ограничения:

  • небольшой объём
  • синхронный доступ

IndexedDB

Асинхронное хранилище для больших данных:

const request = indexedDB.open('app-db', 1)

Преимущества:

  • большой объём
  • структурированные данные
  • поддержка транзакций

Для удобства используются библиотеки:

  • idb
  • dexie

Offline-first подход

Основная идея — приложение должно работать без сети по умолчанию.

Принципы:

  • UI не зависит от сети
  • данные берутся из локального хранилища
  • синхронизация происходит в фоне

Пример логики:

  1. Загрузка данных из IndexedDB
  2. Отображение интерфейса
  3. Попытка обновления через API
  4. Обновление локального хранилища

Очередь действий (Background Sync)

При отсутствии сети действия пользователя можно сохранять и выполнять позже.

Пример:

const queue = []

function addToQueue(action) {
  queue.push(action)
}

При восстановлении соединения:

window.addEventListener('online', async () => {
  for (const action of queue) {
    await sendToServer(action)
  }
  queue.length = 0
})

Service Worker может использовать Background Sync API:

self.registration.sync.register('sync-queue')

Offline fallback

При отсутствии сети можно показывать fallback-страницы:

workbox.routing.setCatchHandler(async ({ event }) => {
  if (event.request.destination === 'document') {
    return caches.match('/offline.html')
  }
})

Используется для:

  • страниц ошибок
  • отсутствующих ресурсов
  • улучшения UX

Обновление Service Worker

Новая версия Service Worker не активируется автоматически.

Настройка:

workboxOptions: {
  skipWaiting: true,
  clientsClaim: true
}

Также можно уведомлять пользователя:

navigator.serviceWorker.addEventListener('controllerchange', () => {
  window.location.reload()
})

Кэширование API-запросов

Пример кэширования API:

workbox.routing.registerRoute(
  ({ url }) => url.pathname.startsWith('/api'),
  new workbox.strategies.NetworkFirst({
    cacheName: 'api-cache',
    networkTimeoutSeconds: 3
  })
)

Добавление fallback:

handlerDidError: async () => {
  return caches.match('/fallback-data.json')
}

Ограничения offline-режима

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

Оптимизация

  • минимизация размера кэша
  • удаление устаревших ресурсов
  • versioning кэша:
const CACHE_NAME = 'app-cache-v1'
  • lazy loading ресурсов
  • разделение статических и динамических данных

Практический паттерн

Комбинация технологий:

  • Service Worker — кэш ресурсов
  • IndexedDB — данные пользователя
  • Network API — отслеживание сети
  • Queue — отложенные действия

Алгоритм:

  1. Приложение загружается из кэша
  2. Данные читаются локально
  3. UI отображается мгновенно
  4. При наличии сети — обновление
  5. При отсутствии — работа в offline
  6. При восстановлении — синхронизация

Интеграция с Quasar Boot

Логика offline может быть вынесена в boot-файл:

export default () => {
  window.addEventListener('offline', () => {
    console.log('Offline режим активен')
  })
}

Подключение в quasar.config.js:

boot: ['offline']

Тестирование offline

В браузере:

  • DevTools → Network → Offline
  • Lighthouse → PWA аудит

Проверяется:

  • загрузка без сети
  • корректность fallback
  • кэширование ресурсов

Безопасность и консистентность

  • контроль версий данных
  • предотвращение конфликтов при синхронизации
  • использование timestamp или versioning

Пример:

if (localVersion < serverVersion) {
  updateData()
}

Расширенные возможности

  • push-уведомления
  • background sync
  • периодическая синхронизация
  • offline аналитика

Все это реализуется через Service Worker и API браузера, а Quasar обеспечивает удобную интеграцию и конфигурацию.