Ответ
Для работы приложения в offline можно использовать Service Workers и Cache API. Вот базовый пример:
// Регистрируем Service Worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then(registration => console.log('SW registered'))
.catch(err => console.log('SW registration failed'));
}
В файле sw.js:
const CACHE_NAME = 'my-app-cache-v1';
const urlsToCache = [
'/',
'/styles.css',
'/app.js',
'/fallback.html'
];
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => cache.addAll(urlsToCache))
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => response || fetch(event.request))
.catch(() => caches.match('/fallback.html'))
);
});
Дополнительно можно использовать:
- IndexedDB для хранения данных
- App Manifest для PWA-функциональности
- Workbox для упрощения работы с кэшированием
Важно тестировать offline-режим в DevTools (Application > Service Workers + Offline checkbox).
Ответ 18+ 🔞
Да ты посмотри, какой народ пошёл — всё им онлайн подавай, серваки свои, облака ебучие. А как интернет отвалится, так сразу: «Ой, всё пропало, приложение не работает, пиздец!». Да не пиздец, а просто ленивые разработчики, которые про оффлайн-режим забыли, как про свою совесть.
Так, слушай сюда, если хочешь, чтобы твоё веб-приложение не помирало, как только пользователь в метро залез, тебе надо подружиться с двумя ребятами: Service Workers и Cache API. Это как два здоровых мужика, которые будут таскать и складировать все нужные файлы прямо у пользователя в браузере. Интернет есть — молодцы, работают. Нет интернета — а им похуй, у них всё своё, под рукой.
Вот смотри, как это замутить. Сначала надо этого самого воркера зарегистрировать, чтоб он начал свою подпольную деятельность.
// Регистрируем Service Worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then(registration => console.log('SW registered'))
.catch(err => console.log('SW registration failed'));
}
А теперь самое интересное — сам файлик sw.js. Тут уже начинается магия, блядь.
const CACHE_NAME = 'my-app-cache-v1';
const urlsToCache = [
'/',
'/styles.css',
'/app.js',
'/fallback.html'
];
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => cache.addAll(urlsToCache))
});
Видишь? На этапе установки он открывает этот кэш, как свой личный склад, и начинает туда аккуратно складывать всё, что ты ему в списке urlsToCache наказал. Главную страницу, стили, скрипты, даже какую-то запасную страничку fallback.html на случай полного пиздеца.
А дальше — ловля запросов. Это как поставить мужика на раздачу:
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => response || fetch(event.request))
.catch(() => caches.match('/fallback.html'))
);
});
Объясняю на пальцах: приходит запрос за каким-нибудь файлом. Наш бравый воркер сначала лезет в свои закрома: «А нет ли у меня этого в кэше?». Если нашёл — сразу отдаёт, быстро, без интернета. Не нашёл — идёт с поклоном в сеть, через fetch. А если и сеть лежит, и в кэше ничего нет — тогда уже, с чувством глубокого пиздеца, выдаёт ту самую запасную страничку, чтоб пользователь не видел страшную ошибку браузера.
Ну и конечно, это только начало, ёпта. Для настоящего оффлайна можно ещё:
- IndexedDB — это уже не просто файлы складировать, а целые базы данных у пользователя в браузере развернуть. Мощная штука.
- App Manifest — чтоб приложение ещё и как родное на телефоне устанавливалось, без всяких маркетов. PWA, блядь, называется.
- Workbox — это такая библиотека-костыль от Гугла, которая всю эту ебучую рутину с кэшированием сильно упрощает. Рекомендую, а то самому всё это писать — терпения ебать ноль.
И главное — не забудь проверить, как это всё работает! В DevTools залезь, на вкладку Application, там и Service Workers посмотреть можно, и галочку «Offline» ткнуть, чтобы симулировать кончину интернета. Если после этого твоё приложение не сдохло, а продолжает работать — значит, ты не зря время потратил, молодец.