Offline функциональность

Preact — легковесный фреймворк для создания пользовательских интерфейсов на JavaScript, и его архитектура позволяет эффективно реализовывать offline-функциональность, минимизируя зависимость приложения от постоянного интернет-соединения. Offline-поддержка включает кеширование ресурсов, управление состоянием при отсутствии сети и синхронизацию данных после восстановления соединения.


Service Workers и Preact

Service Worker — ключевой инструмент для offline-приложений. Он работает как промежуточный слой между браузером и сетью, перехватывая запросы и отдавая кешированные ресурсы, если сеть недоступна.

Основные шаги интеграции Service Worker в Preact:

  1. Регистрация Service Worker:
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/service-worker.js')
    .then(() => console.log('Service Worker зарегистрирован'))
    .catch(err => console.error('Ошибка регистрации:', err));
}
  1. Кеширование ресурсов:
const CACHE_NAME = 'preact-app-cache-v1';
const urlsToCache = [
  '/',
  '/index.html',
  '/bundle.js',
  '/styles.css'
];

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME).then(cache => cache.addAll(urlsToCache))
  );
});
  1. Обработка запросов:
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(response => {
      return response || fetch(event.request);
    })
  );
});

Ключевой момент: кеширование должно быть стратегическим. Например, критические ресурсы (HTML, JS, CSS) кешируются на долгий срок, а динамические данные (API-запросы) — с ограниченным сроком жизни.


Кеширование данных

Offline-приложения требуют сохранения пользовательских данных. Preact легко интегрируется с локальными хранилищами:

  • localStorage — для небольших объёмов данных, синхронизированных вручную.
  • IndexedDB — для структурированных и больших данных.
  • Cache API — для статических ресурсов и сетевых запросов.

Пример использования IndexedDB:

import { openDB } from 'idb';

const dbPromise = openDB('preact-db', 1, {
  upgrade(db) {
    db.createObjectStore('todos', { keyPath: 'id', autoIncrement: true });
  }
});

async function saveTodo(todo) {
  const db = await dbPromise;
  await db.put('todos', todo);
}

async function getTodos() {
  const db = await dbPromise;
  return await db.getAll('todos');
}

Преимущество IndexedDB — возможность хранить сложные структуры и синхронизировать их с сервером при восстановлении сети.


Управление состоянием при offline

Preact использует Hooks и state management, что позволяет контролировать состояние приложения при отсутствии интернета.

Пример:

import { useState, useEffect } from 'preact/hooks';

function Todos() {
  const [todos, setTodos] = useState([]);
  const [online, setOnline] = useState(navigator.onLine);

  useEffect(() => {
    window.addEventListener('online', () => setOnline(true));
    window.addEventListener('offline', () => setOnline(false));

    getTodos().then(setTodos); // загрузка из IndexedDB
  }, []);

  return (
    <div>
      <p>Статус сети: {online ? 'online' : 'offline'}</p>
      <ul>
        {todos.map(todo => <li key={todo.id}>{todo.text}</li>)}
      </ul>
    </div>
  );
}

Важный аспект — сохранение изменений локально при offline и их последующая синхронизация с сервером при подключении сети.


Стратегии кеширования и синхронизации

  • Cache First — сначала проверка кеша, затем сеть. Идеально для статических ресурсов.
  • Network First — сначала запрос к сети, fallback на кеш. Используется для актуальных данных.
  • Stale-While-Revalidate — отдача кеша немедленно, параллельно обновление данных с сервера.

Пример Stale-While-Revalidate для API-запросов:

async function fetchTodos() {
  const cache = await caches.open('api-cache');
  const cachedResponse = await cache.match('/api/todos');

  fetch('/api/todos').then(response => cache.put('/api/todos', response.clone()));

  return cachedResponse ? cachedResponse.json() : fetch('/api/todos').then(res => res.json());
}

Превентивная оптимизация

  1. Минимизировать bundle с помощью Preact CLI или Vite.
  2. Использовать lazy-loading для компонентов и изображений.
  3. Уменьшать размер кешируемых ресурсов, оставляя только критичные.
  4. Логировать и обрабатывать ошибки сети для плавного UX при offline.

Offline-функциональность в Preact строится на комбинации Service Worker, локального хранилища и управления состоянием, что обеспечивает устойчивую работу приложения вне зависимости от стабильности интернет-соединения.