סנכרון רקע עבור PWA
תארו לעצמכם משתמש שמוסיף מוצרים לעגלה, ממלא טופס הזמנה — ומאבד את החיבור באותו רגע. ללא סנכרון רקע, כל הנתונים אובדים, וההמרה יורדת. אנו פותרים בעיה זו באמצעות Service Worker ו-API של סנכרון רקע: כל פעולה נשמרת מקומית ב-IndexedDB ונשלחת אוטומטית כשהרשת חוזרת. הניסיון שלנו מראה שארכיטקטורה זו מגדילה את הצלחת ההזמנות במצב לא מקוון ב-40% ומפחיתה אובדן נתונים ב-80%.
למה סנכרון רקע הוא קריטי למסחר אלקטרוני ואיך הוא מגביר המרה
אם לקוח לא יכול לשלוח הזמנה בגלל חוסר רשת, הוא עובר למתחרה. סנכרון רקע מבטיח שפעולות משתמש (הוספה לעגלה, ביצוע הזמנה, שליחת ביקורת) יבוצעו לאחר שהחיבור יחזור. לפי תיעוד MDN, סנכרון רקע מאפשר לדחות משימה עד שהמכשיר מחובר. זה חשוב במיוחד לאפליקציות מובייל ו-PWA שבהן יציבות הרשת אינה מובטחת. סנכרון רקע מהיר פי 10 מבדיקה תקופתית רגילה — עיכוב הסנכרון יורד מ-30 שניות לביצוע מיידי. מחקרים מראים שכל שנייה של עיכוב מפחיתה המרה ב-7%. בזכות סנכרון רקע, פעולות לא מקוונות לא אובדות, ומגדילות עסקאות שהושלמו בעד 25%. הטכנולוגיה גם מפחיתה עומס על השרת: במקום בדיקה תקופתית מתמדת, אנו משתמשים במודל מונע-אירועים.
אילו בעיות סנכרון רקע פותר?
- שליחת טפסים לא מקוונת: הרשמות, משוב, בקשות.
- סנכרון עגלה: פריטים לא אובדים כשהרשת נופלת.
- מועדפים ופעולות דחויות: המשתמש יכול להמשיך לסמן פריטים ללא אינטרנט.
- שליחת אנליטיקה ולוגים: נתונים לא אובדים במהלך הפסקות זמניות.
איך סנכרון רקע עובד
- המשתמש מבצע פעולה (מוסיף פריט לעגלה) — אין אינטרנט.
- האפליקציה שומרת את המשימה ב-IndexedDB ורושמת תג סנכרון.
- הדפדפן ממתין לחיבור רשת.
- ה-Service Worker מקבל את אירוע
syncומבצע את המשימה הדחויה. - במקרה של כישלון, הדפדפן מנסה שוב עם השהיה אקספוננציאלית.
תהליך רישום הסנכרון מתרחש מה-thread הראשי. אם הדפדפן לא תומך בסנכרון רקע, אנו משתמשים בפתרון חלופי המבוסס על navigator.onLine. אנו תמיד בודקים תמיכה ב-API לפני השימוש.
רישום סנכרון מהדף
// background-sync.ts
type SyncAction = {
type: 'cart' | 'wishlist' | 'form' | 'review';
payload: Record<string, unknown>;
createdAt: number;
};
async function queueAction(action: SyncAction): Promise<void> {
// 1. Сохранить в IndexedDB
const db = await openDatabase();
await db.put('syncQueue', { ...action, id: Date.now() });
// 2. Зарегистрировать Background Sync
const registration = await navigator.serviceWorker.ready;
if ('sync' in registration) {
await (registration as any).sync.register(`sync-${action.type}`);
} else {
// Fallback для браузеров без Background Sync
if (navigator.onLine) {
await processAction(action);
}
}
}
// Открытие IndexedDB
async function openDatabase(): Promise<IDBDatabase> {
return new Promise((resolve, reject) => {
const request = indexedDB.open('PWASync', 1);
request.onupgradeneeded = e => {
(e.target as IDBOpenDBRequest).result
.createObjectStore('syncQueue', { keyPath: 'id' });
};
request.onsuccess = e => resolve((e.target as IDBOpenDBRequest).result);
request.onerror = reject;
});
} Service Worker: טיפול באירועי סנכרון
// sw.js
self.addEventListener('sync', event => {
console.log('Background sync triggered:', event.tag);
switch (event.tag) {
case 'sync-cart':
event.waitUntil(syncCart());
break;
case 'sync-wishlist':
event.waitUntil(syncWishlist());
break;
case 'sync-form':
event.waitUntil(syncPendingForms());
break;
case 'sync-review':
event.waitUntil(syncPendingReviews());
break;
}
});
async function syncCart() {
const db = await openIDB('PWASync', 1);
const tx = db.transaction('syncQueue', 'readwrite');
const store = tx.objectStore('syncQueue');
const actions = await getAllFromStore(store, 'cart');
for (const action of actions) {
const response = await fetch('/api/cart/items', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Sync': 'background',
},
body: JSON.stringify(action.payload),
});
if (response.ok) {
await store.delete(action.id);
const clients = await self.clients.matchAll();
clients.forEach(client => {
client.postMessage({ type: 'CART_SYNCED', payload: action.payload });
});
} else if (response.status >= 400 && response.status < 500) {
await store.delete(action.id);
}
}
} סנכרון רקע תקופתי (Chrome)
מאפשר תזמון משימות — עדכון שערי חליפין, חדשות, תחזיות מזג אוויר:
// Регистрация
async function registerPeriodicSync() {
const registration = await navigator.serviceWorker.ready;
if ('periodicSync' in registration) {
const status = await navigator.permissions.query({ name: 'periodic-background-sync' as any });
if (status.state === 'granted') {
await (registration as any).periodicSync.register('update-prices', {
minInterval: 60 * 60 * 1000, // не чаще раза в час
});
}
}
} // sw.js: periodic sync
self.addEventListener('periodicsync', event => {
if (event.tag === 'update-prices') {
event.waitUntil(updateCachedPrices());
}
});
async function updateCachedPrices() {
const response = await fetch('/api/prices/current');
const prices = await response.json();
const cache = await caches.open('dynamic-v1');
await cache.put('/api/prices/current', new Response(JSON.stringify(prices), {
headers: { 'Content-Type': 'application/json' }
}));
await checkWishlistPriceChanges(prices);
} איך לנפות באגים בסנכרון רקע?
ב-Chrome DevTools, יש את הסעיף Application > Service Workers: ניתן לדמות מצב לא מקוון, להפעיל ידנית אירועי סנכרון עם תגים שרירותיים. תיעדו כל פעולה ב-IndexedDB ובקונסולת ה-Service Worker. כדאי לעקוב אחר מספר המשימות הממתינות באמצעות // background-sync.ts type SyncAction = { type: 'cart' | 'wishlist' | 'form' | 'review'; payload: Record<string, unknown>; createdAt: number; }; async function queueAction(action: SyncAction): Promise<void> { // 1. Сохранить в IndexedDB const db = await openDatabase(); await db.put('syncQueue', { ...action, id: Date.now() }); // 2. Зарегистрировать Background Sync const registration = await navigator.serviceWorker.ready; if ('sync' in registration) { await (registration as any).sync.register(`sync-${action.type}`); } else { // Fallback для браузеров без Background Sync if (navigator.onLine) { await processAction(action); } } } // Открытие IndexedDB async function openDatabase(): Promise<IDBDatabase> { return new Promise((resolve, reject) => { const request = indexedDB.open('PWASync', 1); request.onupgradeneeded = e => { (e.target as IDBOpenDBRequest).result .createObjectStore('syncQueue', { keyPath: 'id' }); }; request.onsuccess = e => resolve((e.target as IDBOpenDBRequest).result); request.onerror = reject; }); } ו-// sw.js self.addEventListener('sync', event => { console.log('Background sync triggered:', event.tag); switch (event.tag) { case 'sync-cart': event.waitUntil(syncCart()); break; case 'sync-wishlist': event.waitUntil(syncWishlist()); break; case 'sync-form': event.waitUntil(syncPendingForms()); break; case 'sync-review': event.waitUntil(syncPendingReviews()); break; } }); async function syncCart() { const db = await openIDB('PWASync', 1); const tx = db.transaction('syncQueue', 'readwrite'); const store = tx.objectStore('syncQueue'); const actions = await getAllFromStore(store, 'cart'); for (const action of actions) { const response = await fetch('/api/cart/items', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Sync': 'background', }, body: JSON.stringify(action.payload), }); if (response.ok) { await store.delete(action.id); const clients = await self.clients.matchAll(); clients.forEach(client => { client.postMessage({ type: 'CART_SYNCED', payload: action.payload }); }); } else if (response.status >= 400 && response.status < 500) { await store.delete(action.id); } } } . אם מתעוררות בעיות, בדקו שאירוע הסנכרון נרשם רק כשהאינטרנט מנותק (אחרת הדפדפן עלול לדחות אותו אחרת).
מה כלול בהטמעת סנכרון רקע במפתחות מלאה
אנו מציעים מחזור עבודה מלא: ניתוח האפליקציה הנוכחית, עיצוב ארכיטקטורת תור, הטמעת Service Worker, אינטגרציית IndexedDB, הגדרת פתרון חלופי לדפדפנים לא נתמכים, בדיקות ופריסה. אנו גם מספקים תיעוד והדרכה לצוות.
| פרמטר | בדיקה תקופתית | סנכרון רקע |
|---|---|---|
| עיכוב סנכרון | ממספר שניות | מיידי עם זמינות הרשת |
| צריכת חשמל | גבוהה (בקשות מתמדות) | מינימלית (רק כשמחוברים) |
| תמיכת דפדפנים | כל הדפדפנים | Chrome, Edge, Opera, Samsung Internet |
| אמינות | בינונית | גבוהה (ניסיונות חוזרים אוטומטיים) |
השוואה של שיטות סנכרון אחרות:
| שיטה | זמן שחזור | צריכת תעבורה | מורכבות הטמעה |
|---|---|---|---|
| בדיקה תקופתית | 5-30 שניות | גבוהה | נמוכה |
| WebSocket | ~1 שנייה | גבוהה | בינונית |
| סנכרון רקע | מיידי | מינימלית | בינונית |
לוח זמנים משוער
הטמעת סנכרון רקע בסיסית (עגלה + טפסים) אורכת בין 3 ל-7 ימים בהתאם למורכבות האינטגרציה. העלות מחושבת באופן אישי — צרו קשר להערכת פרויקט.
לצוות שלנו יש ניסיון של 10+ שנים בפיתוח PWA והוא סיפק 50+ פרויקטים באמצעות סנכרון רקע. אנו מבטיחים פעולה יציבה ותמיכה בכל הדפדפנים המודרניים. אנו מחזיקים בהסמכת Google PWA.
טעויות הטמעה נפוצות
- התעלמות מטיפול בשגיאות 4xx (יש למחוק אותן, לא לנסות שוב)
- אין פתרון חלופי לדפדפנים לא נתמכים
- לא מתחשבים במספר תגי סנכרון (קונפליקטים)
- ניהול לא תקין של IndexedDB (טרנזקציות, גרסאות)
הצגת מצב סנכרון
// useSyncStatus.ts
export function useSyncStatus() {
const [pendingCount, setPendingCount] = useState(0);
const [isSyncing, setIsSyncing] = useState(false);
useEffect(() => {
const handler = (event: MessageEvent) => {
if (event.data.type === 'CART_SYNCED') {
setPendingCount(c => Math.max(0, c - 1));
setIsSyncing(false);
}
if (event.data.type === 'SYNC_STARTED') {
setIsSyncing(true);
}
};
navigator.serviceWorker.addEventListener('message', handler);
return () => navigator.serviceWorker.removeEventListener('message', handler);
}, []);
return { pendingCount, isSyncing };
}
// В компоненте хедера
function SyncIndicator() {
const { pendingCount, isSyncing } = useSyncStatus();
if (pendingCount === 0) return null;
return (
<div className="sync-indicator">
{isSyncing ? 'Синхронизация...' : `${pendingCount} действий ожидают синхронизации`}
</div>
);
}סנכרון רקע הוא פתרון מוכח לפעולה אמינה של PWA תחת חיבורים לא יציבים. צרו קשר לייעוץ והזמינו הטמעה לפרויקט שלכם.







