PWA с Vue

Progressive Web App (PWA) представляет собой веб-приложение, которое сочетает возможности обычного веб-сайта и нативного приложения. Основные преимущества PWA включают работу офлайн, быструю загрузку и возможность установки на устройство пользователя. Vue.js, благодаря своей модульной архитектуре и поддержке экосистемы инструментов, предоставляет удобный путь для создания PWA.

Настройка проекта Vue для PWA

Для создания PWA на Vue обычно используется Vue CLI, который поддерживает шаблон PWA. При инициализации проекта через vue create можно выбрать плагин PWA. Этот плагин автоматически интегрирует:

  • Service Worker через workbox-webpack-plugin
  • manifest.json с базовыми метаданными приложения
  • Базовую конфигурацию для кэширования ресурсов

Пример добавления плагина в существующий проект:

vue add pwa

После установки плагина автоматически создается структура:

public/
 ├─ manifest.json
 └─ icons/
src/
 └─ registerServiceWorker.js

Конфигурация manifest.json

Файл manifest.json описывает PWA и содержит ключевые параметры:

{
  "name": "Vue PWA App",
  "short_name": "VuePWA",
  "start_url": ".",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#4DBA87",
  "icons": [
    {
      "src": "icons/icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "icons/icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}
  • name — полное название приложения.
  • short_name — сокращенное название для ярлыков.
  • start_url — URL, с которого запускается приложение.
  • display — режим отображения (standalone обеспечивает вид нативного приложения).
  • theme_color — цвет интерфейса браузера.
  • icons — иконки различных размеров для установки на устройства.

Service Worker и кэширование

Service Worker позволяет работать с приложением офлайн и кэшировать ресурсы. В Vue CLI по умолчанию используется registerServiceWorker.js:

import { register } from 'register-service-worker'

if (process.env.NODE_ENV === 'production') {
  register(`${process.env.BASE_URL}service-worker.js`, {
    ready() {
      console.log('App is being served from cache by a service worker.')
    },
    registered() {
      console.log('Service worker has been registered.')
    },
    cached() {
      console.log('Content has been cached for offline use.')
    },
    updatefound() {
      console.log('New content is downloading.')
    },
    updated() {
      console.log('New content is available; please refresh.')
    },
    offline() {
      console.log('No internet connection found. App is running in offline mode.')
    },
    error(error) {
      console.error('Error during service worker registration:', error)
    }
  })
}

Основные этапы работы Service Worker:

  1. Установка (install) — определение ресурсов, которые необходимо кэшировать.
  2. Активация (activate) — удаление устаревших кэшей.
  3. Фетч (fetch) — перехват сетевых запросов и отдача данных из кэша при отсутствии соединения.

Кэширование с Workbox

Workbox позволяет более гибко управлять кэшированием. В vue.config.js можно настроить стратегию:

module.exports = {
  pwa: {
    workboxOptions: {
      runtimeCaching: [
        {
          urlPattern: /\/api\/.*\/*.json/,
          handler: 'NetworkFirst',
          options: {
            cacheName: 'api-cache',
            expiration: {
              maxEntries: 50,
              maxAgeSeconds: 86400
            }
          }
        },
        {
          urlPattern: /\.(?:png|jpg|jpeg|svg|gif)$/,
          handler: 'CacheFirst',
          options: {
            cacheName: 'image-cache',
            expiration: {
              maxEntries: 100,
              maxAgeSeconds: 2592000
            }
          }
        }
      ]
    }
  }
}
  • NetworkFirst — сначала пробует сеть, потом кэш.
  • CacheFirst — сначала кэш, потом сеть.
  • cacheName — имя кэша для удобного управления.
  • expiration — параметры хранения кэшированных данных.

Работа с уведомлениями и офлайн-функциями

Для полноценного PWA часто используются push-уведомления и офлайн-функции:

  • Push API интегрируется через Service Worker.
  • IndexedDB или localStorage используются для хранения данных при офлайн-режиме.

Пример записи данных в IndexedDB через библиотеку idb:

import { openDB } from 'idb';

const dbPromise = openDB('vue-pwa-db', 1, {
  upgrade(db) {
    db.createObjectStore('posts', { keyPath: 'id' });
  }
});

async function savePost(post) {
  const db = await dbPromise;
  await db.put('posts', post);
}

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

Оптимизация и лучшие практики

  • Минимизировать размер кэша, кэшировать только необходимые файлы.
  • Использовать динамическое кэширование для API-запросов.
  • Обновлять Service Worker через стратегию «Stale-while-revalidate».
  • Поддерживать manifest.json в актуальном состоянии, включая иконки разных размеров.
  • Тестировать офлайн-функциональность с помощью инструментов Chrome DevTools.

Интеграция с Vue Router и Vuex

  • Vue Router: маршруты должны корректно работать в офлайн-режиме, поэтому кэшируются важные страницы.
  • Vuex: состояние приложения можно сохранять в IndexedDB или localStorage для восстановления при повторном запуске PWA.

Пример интеграции Vuex с localStorage:

const store = new Vuex.Store({
  state: {
    user: JSON.parse(localStorage.getItem('user')) || null
  },
  mutations: {
    setUser(state, user) {
      state.user = user;
      localStorage.setItem('user', JSON.stringify(user));
    }
  }
});

PWA на Vue.js позволяет создавать приложения, которые быстро загружаются, работают офлайн и обеспечивают удобный пользовательский опыт, приближенный к нативным мобильным приложениям.