PageSourceSearch

https://woxi.ru/service-worker.js

js woxi.ru collected 2026-10-05 00:20:26 UTC 3,840 bytes, 80 lines download raw bytes

1/* Вокси — service worker.
2 * Задачи: (1) делает сайт устанавливаемым (PWA), (2) показывает страницу «Нет соединения» вместо ошибки браузера,
3 * (3) ускоряет повторные визиты: картинки и шрифты берутся из кэша и тихо обновляются; стили и скрипты — из сети, кэш только на случай отсутствия связи.
4 * Страницы (HTML), личные кабинеты, админка, запросы POST и любые JSON/AJAX-ответы НЕ кэшируются —
5 * чтобы никогда не показывать чужие или устаревшие данные (в том числе на общем устройстве).
6 * При изменении логики поднимайте VERSION — старые кэши удалятся сами. */
7const VERSION = 'v3';
8const STATIC_CACHE = 'woxi-static-' + VERSION;
9const OFFLINE_URL = '/offline.html';
10const PRECACHE = [OFFLINE_URL, '/pwa/icon-192.png', '/pwa/icon-512.png'];
11
12self.addEventListener('install', event => {
13  event.waitUntil(caches.open(STATIC_CACHE).then(cache => cache.addAll(PRECACHE)).then(() => self.skipWaiting()));
14});
15
16self.addEventListener('activate', event => {
17  event.waitUntil(
18    caches.keys()
19      .then(keys => Promise.all(keys.filter(key => key !== STATIC_CACHE).map(key => caches.delete(key))))
20      .then(() => self.clients.claim())
21  );
22});
23
24// Картинки и шрифты — из кэша с тихим обновлением; стили и скрипты — сначала сеть (чтобы не отдавать устаревший код после обновления сайта), кэш только как запасной вариант без сети
25function classify(url) {
26  if (url.origin !== self.location.origin) return null;
27  var ok = url.pathname.indexOf('/resources/') === 0 || url.pathname.indexOf('/storage/') === 0 || url.pathname.indexOf('/pwa/') === 0;
28  if (!ok) return null;
29  if (/\.(?:woff2?|ttf|svg|png|jpe?g|webp|gif|ico)$/i.test(url.pathname)) return 'media';
30  if (/\.(?:css|js)$/i.test(url.pathname)) return 'code';
31  return null;
32}
33
34self.addEventListener('fetch', event => {
35  const request = event.request;
36
37  if (request.method !== 'GET') return;
38
39  const url = new URL(request.url);
40
41  if (url.origin !== self.location.origin) return;
42
43  // Переходы по страницам: всегда из сети; если сети нет — страница «Нет соединения»
44  if (request.mode === 'navigate') {
45    event.respondWith(
46      fetch(request).catch(() => caches.match(OFFLINE_URL).then(r => r || Response.error()))
47    );
48    return;
49  }
50
51  const kind = classify(url);
52
53  if (kind === 'media') {
54    event.respondWith(
55      caches.open(STATIC_CACHE).then(cache =>
56        cache.match(request).then(cached => {
57          const network = fetch(request).then(response => {
58            if (response && response.ok && response.type === 'basic') cache.put(request, response.clone());
59            return response;
60          }).catch(() => cached);
61          return cached || network;
62        })
63      )
64    );
65    return;
66  }
67
68  if (kind === 'code') {
69    event.respondWith(
70      fetch(request).then(response => {
71        if (response && response.ok && response.type === 'basic') {
72          const copy = response.clone();
73          caches.open(STATIC_CACHE).then(cache => cache.put(request, copy));
74        }
75        return response;
76      }).catch(() => caches.match(request).then(r => r || Response.error()))
77    );
78  }
79  // всё остальное (AJAX, JSON, админка, чат) — напрямую в сеть, без вмешательства
80});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.