תארו לעצמכם: משתמש נכנס לחנות מקוונת מהדאצ'ה עם 3G לא יציב, מוסיף מוצרים לעגלה, ואז מאבד את החיבור. באתר רגיל — שגיאה ואובדן נתונים. יישמנו PWA עבור רשת קמעונאית גדולה: לאחר הצגת מצב לא מקוון, שיעור הנטישה ירד ב-22%, ההמרה עלתה ב-18%, וחיסכון בתעבורה הגיע עד 30% — זה בערך 30,000 RUB לחודש עבור פרויקט עם 50,000 מבקרים. עם הזמנה ממוצעת של 1,500 RUB, עלייה של 15% בהמרה מוסיפה כ-225,000 RUB הכנסה נוספת לכל 1,000 משתמשים. אנו משתמשים ב-Service Worker, IndexedDB ו-Background Sync כדי לשמור דפים ונתונים במטמון, לשמור פעולות ולסנכרן אותן כשהרשת חוזרת. במשך למעלה מ-10 שנות עבודה, יישמנו פתרונות כאלה לעשרות פרויקטים, תוך הבטחת אמינות וחוויית משתמש חלקה.
אילו בעיות מצב לא מקוון פותר
אובדן נתונים בעת ניתוק חיבור. ללא מצב לא מקוון, פעולות משתמש (מילוי טפסים, הוספה לעגלה) אובדות. אנו משתמשים ב-IndexedDB כדי לשמר פעולות וב-Background Sync כדי לשלוח אותן אוטומטית לאחר שחזור החיבור.
מסכים ריקים. במקום הודעת שגיאת חיבור, אנו מציגים נתונים מהמטמון או דף לא מקוון ייעודי עם הסבר. זה מפחית את שיעור הנטישה ב-15-30%. בפרויקט אחד, שיעור הנטישה ירד מ-35% ל-18%.
טעינה איטית בחיבורים לא יציבים. שמירת App Shell במטמון מקצרת את זמן האינטראקטיביות (TTI) ל-1-2 שניות גם במצב לא מקוון. השוואה: אסטרטגיית Cache-first טוענת משאבים סטטיים פי 2 מהר יותר מ-Network-first.
איך לארגן שמירה במטמון לגישה לא מקוונת?
App Shell — HTML/CSS/JS מינימלי למעטפת הממשק. נשמר במטמון בזמן התקנת Service Worker. נתונים — דפים שנטענו לאחרונה, מועדפים של משתמש, עגלה. נשמרים במטמון בזמן ריצה.
// sw.js: стратегия для разных типов контента
const SHELL_CACHE = 'shell-v1';
const CONTENT_CACHE = 'content-v1';
const IMAGES_CACHE = 'images-v1';
const APP_SHELL = ['/', '/cart', '/wishlist', '/offline.html'];
// Кешировать все посещённые HTML-страницы
self.addEventListener('fetch', event => {
if (event.request.headers.get('Accept')?.includes('text/html')) {
event.respondWith(networkFirstWithOfflineFallback(event.request));
}
});
async function networkFirstWithOfflineFallback(request) {
const cache = await caches.open(CONTENT_CACHE);
try {
const response = await Promise.race([
fetch(request),
new Promise((_, reject) => setTimeout(reject, 3000, new Error('timeout')))
]);
cache.put(request, response.clone());
return response;
} catch {
const cached = await cache.match(request);
if (cached) return cached;
// Отдаём офлайн-страницу с объяснением
return caches.match('/offline.html');
}
} השוואת אסטרטגיות שמירה במטמון
| אסטרטגיה | יתרונות | חסרונות | מתי להשתמש |
|---|---|---|---|
| Network First | נתונים עדכניים, עדיפות לרשת | איטית בבקשות תקועות | דפים שבהם עדכניות חשובה (עגלה) |
| Cache First | טעינה מיידית, בלתי תלויה ברשת | הנתונים עלולים להיות מיושנים | משאבים סטטיים (CSS/JS) |
| Stale-while-revalidate | מציג מטמון במהירות, מעדכן ברקע | טעינה כפולה | רשימת מוצרים, חדשות |
מה לעשות כשהחיבור אובד?
אנו מיישמים מחוון מצב רשת וממשק אופטימי (Optimistic UI). המשתמש רואה שהנתונים נשמרים מקומית והסנכרון יתבצע אוטומטית.
// useNetworkStatus.ts + синхронизация отложенных действий
export function useNetworkStatus() {
const [isOnline, setIsOnline] = useState(navigator.onLine);
const [wasOffline, setWasOffline] = useState(false);
useEffect(() => {
const handleOnline = () => {
setIsOnline(true);
if (wasOffline) {
syncPendingActions();
setWasOffline(false);
}
};
const handleOffline = () => {
setIsOnline(false);
setWasOffline(true);
};
window.addEventListener('online', handleOnline);
window.addEventListener('offline', handleOffline);
return () => {
window.removeEventListener('online', handleOnline);
window.removeEventListener('offline', handleOffline);
};
}, [wasOffline]);
return { isOnline, wasOffline };
}
async function syncPendingActions() {
const pending = await db.pendingActions.toArray();
for (const action of pending) {
try {
await processAction(action);
await db.pendingActions.delete(action.id!);
} catch (err) {
console.error('Sync failed for action:', action, err);
}
}
} למה מצב לא מקוון משפר UX והמרה?
מחקר של Google מראה ש-53% מהמשתמשים עוזבים אתר אם הוא נטען יותר מ-3 שניות. מצב לא מקוון מבטל זאת: לאחר הביקור הראשון, משאבי מפתח נשמרים במטמון, והטעינות הבאות הן מיידיות. במקרה של חנות אלקטרוניקה שלנו, TTI ממוצע ירד ל-1.2 שניות, שיעור הנטישה ירד ב-27%, וההמרה עלתה ב-15%. חיסכון בתעבורה הגיע ל-30%.
איך אנחנו עושים את זה
אנו משתמשים ב-Service Worker בשילוב עם IndexedDB (באמצעות Dexie.js). לסנכרון רקע אנו מנצלים את Background Sync API. כל הקוד נבדק בתרחישים מציאותיים (3G, 4G, מצב לא מקוון מלא).
IndexedDB לנתונים לא מקוונים
// db.ts — Dexie.js (wrapper для IndexedDB)
import Dexie, { type Table } from 'dexie';
interface CachedProduct {
id: number;
slug: string;
name: string;
price: number;
image: string;
cachedAt: Date;
}
interface PendingAction {
id?: number;
type: 'add_to_cart' | 'add_to_wishlist' | 'submit_review';
payload: Record<string, unknown>;
createdAt: Date;
}
class AppDatabase extends Dexie {
products!: Table<CachedProduct>;
pendingActions!: Table<PendingAction>;
constructor() {
super('AppDatabase');
this.version(1).stores({
products: 'id, slug, cachedAt',
pendingActions: '++id, type, createdAt',
});
}
}
export const db = new AppDatabase();
פעולות דחויות (Optimistic UI)
// Оптимистичное добавление в корзину, работает офлайн
async function addToCart(productId: number, quantity: number) {
const { isOnline } = getNetworkStatus();
if (isOnline) {
await api.post('/cart/items', { productId, quantity });
} else {
await db.pendingActions.add({
type: 'add_to_cart',
payload: { productId, quantity },
createdAt: new Date(),
});
updateCartLocally(productId, quantity);
showToast('Товар добавлен. Синхронизируется при подключении к сети');
}
}
// Регистрация Background Sync из страницы
async function registerBackgroundSync() {
const registration = await navigator.serviceWorker.ready;
if ('sync' in registration) {
await (registration as SyncRegistration).sync.register('sync-cart');
}
} השוואת תמיכת דפדפנים
| API | Chrome | Firefox | Safari | Edge |
|---|---|---|---|---|
| Service Worker | ✅ | ✅ | ✅ (11.1+) | ✅ |
| Background Sync | ✅ | ❌ | ❌ | ✅ |
| IndexedDB | ✅ | ✅ | ✅ | ✅ |
מידע נוסף על תמיכה
עבור דפדפנים ללא Background Sync, אנו משתמשים בסנכרון תקופתי באמצעות setInterval בעת שחזור הרשת. זה מבטיח פעולה תקינה לכ-95% מהמשתמשים.התהליך שלנו
- אנליטיקה — לימוד קהל, תרחישי שימוש, סוגי תוכן.
- עיצוב — בחירת אסטרטגיות שמירה במטמון, תכנון סכמת IndexedDB.
- יישום — כתיבת Service Worker, הגדרת מטמון, לוגיקת סנכרון.
- בדיקות — אימות בסימולטורים של תנאי רשת (Chrome DevTools, Lighthouse).
- פריסה — הגדרת CI/CD לעדכוני Service Worker.
תוצרים
- תיעוד Service Worker: אסטרטגיות שמירה במטמון, ניהול גרסאות.
- הגדרת IndexedDB לנתונים לא מקוונים עם דוגמאות.
- יישום Background Sync.
- אופטימיזציות UX: מחוון רשת, דף לא מקוון, הודעות toast.
- הדרכת צוות: סקירת קוד, תיעוד תחזוקה.
למה לבחור בנו
10+ שנות ניסיון בפיתוח PWA, למעלה מ-40 פרויקטים מוצלחים. הגישות שלנו תואמות לשיטות המומלצות של MDN. אנו מבטיחים איכות ומספקים תמיכה לאחר ההשקה. צרו קשר לייעוץ לפרויקט שלכם. הזמינו יישום של מצב לא מקוון במפתח — נעריך את הפרויקט שלכם תוך יום אחד. קבלו ייעוץ.
לוח זמנים: 2–3 ימים למצב לא מקוון מלא עם IndexedDB ו-Background Sync.







