PWA — React da Progressive Web App
Muammodan boshlaylik
Siz vazifalar ro'yxati ilovasini yasadingiz. Foydalanuvchilar so'raydi:
- "Telefonda ilova sifatida o'rnatsa bo'ladimi? Har safar brauzer ochib, manzil yozish noqulay"
- "Metroda internet yo'q — ilova ochilmayapti"
- "Har safar ochganda yuklanishi sekin"
Mobil ilova (React Native) yasash — alohida loyiha, App Store va Google Play ga joylash, ko'rib chiqish jarayonlari. Ko'p hollarda bu ortiqcha.
PWA (Progressive Web App) — oddiy veb-saytga ilova imkoniyatlarini qo'shish: o'rnatish, offlayn ishlash, tez yuklanish. Bir xil React kod — brauzerda ham, "ilova" sifatida ham.
PWA nimadan iborat
Uch qism:
| Qism | Vazifasi |
|---|---|
| HTTPS | Majburiy (faqat localhost istisno) |
| Web App Manifest | Ilova haqida: nomi, ikonkalar, ranglar, qanday ochilishi |
| Service Worker | Fonda ishlaydigan skript: keshlash, offlayn, yangilanishlar |
Shu uchtasi bo'lsa — brauzer "Ilovani o'rnatish" ni taklif qiladi, va o'rnatilgan ilova o'z ikonkasi bilan, brauzer paneli siz, alohida oynada ochiladi.
vite-plugin-pwa
Service Worker ni qo'lda yozish murakkab. Vite uchun tayyor plagin:
npm install -D vite-plugin-pwa
// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { VitePWA } from 'vite-plugin-pwa';
export default defineConfig({
plugins: [
react(),
VitePWA({
registerType: 'prompt',
includeAssets: ['favicon.svg', 'apple-touch-icon.png'],
manifest: {
name: 'Vazifalar — kundalik rejalashtiruvchi',
short_name: 'Vazifalar',
description: "Kunlik vazifalarni rejalashtirish va kuzatish",
lang: 'uz',
start_url: '/',
display: 'standalone',
background_color: '#ffffff',
theme_color: '#10b981',
icons: [
{ src: '/icons/192.png', sizes: '192x192', type: 'image/png' },
{ src: '/icons/512.png', sizes: '512x512', type: 'image/png' },
{ src: '/icons/512-maskable.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' },
],
},
}),
],
});
npm run build dan keyin plagin avtomatik yaratadi:
manifest.webmanifestva uniindex.htmlga ulaydisw.js— barcha build fayllarini (JS, CSS, HTML, ikonkalar) oldindan keshlovchi Service Worker- Service Worker ni ro'yxatdan o'tkazish kodi
Manifest maydonlari
| Maydon | Ma'nosi |
|---|---|
name / short_name |
To'liq nom (o'rnatish oynasida) / qisqa nom (ikonka ostida) |
start_url |
Ilova ochilganda qaysi sahifa |
display |
standalone — brauzer paneli siz, ilova kabi; browser — oddiy tab |
theme_color |
Holat paneli va sarlavha rangi |
background_color |
Yuklanish ekrani (splash) foni |
icons |
Kamida 192×192 va 512×512; maskable — Android ning dumaloq/kvadrat shakllariga moslashadigan ikonka |
[!TIP] Ikonkalarni bitta katta rasmdan yaratish uchun
@vite-pwa/assets-generatorvositasi bor. Maskable ikonka uchun muhim kontent markazdagi xavfsiz zonada (taxminan 80%) bo'lishi kerak — aks holda Android uni kesib qo'yadi.
Service Worker qanday ishlaydi
Brauzer Service Worker Tarmoq
│ │ │
│── GET /app.js ───────▶│ │
│ │── keshda bormi? ──┐ │
│ │◀── ha ─────────────┘ │
│◀── keshdan (0 ms) ─────│ │
│ │ │
│── GET /api/vazifalar ─▶│──────────────────────▶│
│ │◀───────────────────────│
│◀───────────────────────│ (+ keshga nusxa) │
Service Worker — brauzer va tarmoq o'rtasidagi proksi. U har bir so'rovni ushlaydi va qaror qiladi: keshdan berish, tarmoqqa yuborish yoki ikkalasi.
Natija:
- Ikkinchi ochilishdan boshlab ilova bir zumda yuklanadi — fayllar keshdan
- Internet bo'lmasa ham ochiladi — interfeys keshda
API so'rovlarini keshlash
Standart holatda faqat ilova fayllari keshlanadi. API ma'lumotlari uchun — runtimeCaching:
VitePWA({
workbox: {
runtimeCaching: [
{
urlPattern: ({ url }) => url.pathname.startsWith('/api/'),
handler: 'NetworkFirst',
options: {
cacheName: 'api',
networkTimeoutSeconds: 3,
expiration: { maxEntries: 100, maxAgeSeconds: 60 * 60 * 24 },
},
},
{
urlPattern: ({ request }) => request.destination === 'image',
handler: 'CacheFirst',
options: {
cacheName: 'rasmlar',
expiration: { maxEntries: 200, maxAgeSeconds: 60 * 60 * 24 * 30 },
},
},
],
},
});
| Strategiya | Qanday ishlaydi | Qachon |
|---|---|---|
CacheFirst |
Avval kesh; yo'q bo'lsa — tarmoq | Rasmlar, shriftlar — o'zgarmaydigan resurslar |
NetworkFirst |
Avval tarmoq; ishlamasa — kesh | API ma'lumotlari — yangi bo'lishi muhim, lekin offlayn ham kerak |
StaleWhileRevalidate |
Darhol keshdan + fonda yangilash | Tez-tez o'zgarmaydigan ma'lumotlar: kategoriyalar, profil |
NetworkOnly |
Faqat tarmoq | To'lov, autentifikatsiya |
[!WARNING] Shaxsiy ma'lumotlarni (buyurtmalar, xabarlar) Service Worker keshiga qo'yishda ehtiyot bo'ling: foydalanuvchi tizimdan chiqqandan keyin ham ular keshda qoladi va umumiy kompyuterda boshqa odam ko'rishi mumkin. Chiqishda keshni tozalang (
caches.delete('api')) yoki shaxsiy API larni keshlamang.
Yangilanishlar
PWA ning eng nozik qismi. Siz yangi versiya deploy qildingiz — lekin foydalanuvchi eski versiyani ko'radi, chunki u keshdan yuklanmoqda.
registerType: 'prompt' bilan — foydalanuvchiga xabar ko'rsatish:
// src/components/YangilanishXabari.jsx
import { useRegisterSW } from 'virtual:pwa-register/react';
function YangilanishXabari() {
const {
needRefresh: [yangilanishBor, setYangilanishBor],
updateServiceWorker,
} = useRegisterSW();
if (!yangilanishBor) return null;
return (
<div role="status" className="yangilanish-banner">
<p>Yangi versiya mavjud.</p>
<button onClick={() => updateServiceWorker(true)}>Yangilash</button>
<button onClick={() => setYangilanishBor(false)}>Keyinroq</button>
</div>
);
}
prompt— foydalanuvchi o'zi tanlaydi; forma to'ldirayotgan odamning ishi yo'qolmaydiautoUpdate— avtomatik yangilanadi; oddiyroq, lekin sahifa kutilmaganda qayta yuklanishi mumkin
[!INFO] Server da
sw.jsvaindex.htmlfayllari keshlanmasligi kerak (Cache-Control: no-cache) — aks holda brauzer yangi Service Worker borligini bilmaydi. Hash li JS/CSS fayllar esa uzoq muddat keshlanadi (72-dars).
Offlayn holatni ko'rsatish
import { useSyncExternalStore } from 'react';
function onlaynObuna(callback) {
window.addEventListener('online', callback);
window.addEventListener('offline', callback);
return () => {
window.removeEventListener('online', callback);
window.removeEventListener('offline', callback);
};
}
function useOnlayn() {
return useSyncExternalStore(onlaynObuna, () => navigator.onLine, () => true);
}
function OfflaynBanner() {
const onlayn = useOnlayn();
if (onlayn) return null;
return <div role="status">Internet aloqasi yo'q. Ma'lumotlar oxirgi saqlangan holatda.</div>;
}
TanStack Query offlayn holatni o'zi kuzatadi: aloqa uzilganda so'rovlarni to'xtatadi va tiklanganda qayta yuboradi (54-dars, refetchOnReconnect).
Development da tekshirish
Service Worker standart holatda faqat production build da ishlaydi:
npm run build
npm run preview
Chrome DevTools → Application tabi:
- Manifest — xatolar va ogohlantirishlar, ikonkalar
- Service Workers — holati, "Update on reload", "Offline" belgisi
- Cache Storage — nimalar keshlangan
Lighthouse → PWA tekshiruvi ham foydali.
Cheklovlar
- iOS (Safari) — PWA ni qo'llab-quvvatlaydi, lekin cheklovlar bilan: o'rnatish faqat "Ulashish → Uy ekraniga qo'shish" orqali (avtomatik taklif yo'q), push bildirishnomalar faqat o'rnatilgan ilovada va iOS ning yangi versiyalarida
- Ba'zi qurilma imkoniyatlari (Bluetooth, NFC, fon rejimida uzoq ishlash) — cheklangan yoki faqat ba'zi brauzerlarda
- Do'konlarda (App Store) ko'rinmaydi — lekin Google Play ga TWA (Trusted Web Activity) orqali joylash mumkin
Nima uchun shunday?
Nima uchun Service Worker sahifadan alohida, fonda ishlaydi — keshlashni oddiy JavaScript bilan qilsa bo'lmaydimi?
Chunki sahifaning JavaScript i sahifa yuklangandan keyin ishlay boshlaydi — va sahifani yuklash uchun internet kerak. Offlayn holatda sahifa umuman ochilmaydi, demak uning kodi ham ishga tushmaydi. Service Worker esa brauzerda sahifadan mustaqil ro'yxatdan o'tgan va sahifa so'rovidan oldin ishga tushadigan skript. U "sahifani qayerdan olish kerak?" degan savolga javob beradi — tarmoq ishlamasa ham. Bu mobil ilovalar modelini veb ga olib keladi: ilova kodi qurilmada saqlanadi, tarmoq esa faqat ma'lumot uchun kerak.
Xulosa
Eslab qoling:
- PWA = HTTPS + Web App Manifest + Service Worker → o'rnatish, offlayn, tez yuklanish
vite-plugin-pwa— manifest va Service Worker ni avtomatik yaratadi- Manifest:
name,short_name,start_url,display: 'standalone',theme_color, ikonkalar 192/512 + maskable - Service Worker — brauzer va tarmoq o'rtasidagi proksi; ilova fayllari oldindan keshlanadi
- API keshlash —
runtimeCaching:CacheFirst,NetworkFirst,StaleWhileRevalidate; shaxsiy ma'lumotlarga ehtiyot - Yangilanishlar —
registerType: 'prompt'+useRegisterSW;sw.jsvaindex.htmlkeshlanmasin - Tekshirish — production build, DevTools → Application; iOS cheklovlarini hisobga oling
Keyingi dars
88-dars: React bilan real loyiha arxitekturasi — papkalar tuzilishi