בעיה: נתונים בתוסף אובדים או אינם מסונכרנים
בעת פיתוח תוסף לדפדפן Chrome, אחת הטעויות הנפוצות ביותר היא אובדן נתונים בעת הפעלה מחדש של service worker או אי-סנכרון הגדרות בין מכשירי המשתמש. מפתחים מתחילים רבים מסתמכים על localStorage, אך הוא אינו פועל בסקריפטים ברקע תחת Manifest V3 ואינו מודיע על שינויים בהקשרים אחרים. כתוצאה מכך, משתמש משנה את הערכת הנושא במחשב הנייד — המחשב השולחני עדיין מציג את הנושא הישן, ומטמון התרגום נעלם לאחר 30 שניות של חוסר פעילות. באחד הפרויקטים שלנו — תוסף מתרגם עם 10,000 משתמשים פעילים — נתקלנו באובדן מטמון בכל הפעלה מחדש של service worker. הפתרון היה פשוט: שילוב של chrome.storage.sync להגדרות ו-chrome.storage.local למטמון. יישמנו אחסון עבור למעלה מ-50 תוספים ויש לנו 5 שנות ניסיון בתחום זה.
בעיות שאנו פותרים
הגדרות שאינן מסונכרנות מתרחשות כאשר משתמש משנה את הנושא במכשיר אחד אך השני עדיין מציג את הישן. chrome.storage.sync מסנכרן נתונים אוטומטית דרך חשבון Google של המשתמש; המגבלה היא 100 KB, וזה מספיק לתצורה.
אובדן מטמון בעת הפעלה מחדש של service worker הוא בעיה אופיינית של Manifest V3: ה-SW נטען מחדש לאחר 30 שניות של חוסר פעילות. אחסון מטמון במשתנים יגרום לאובדן שלו. chrome.storage.local או session פותרים את הבעיה.
חוסר בטיפוסים מוביל לשגיאות בעת קריאת נתונים, במיוחד במהלך מיגרציות סכמה. אנו יוצרים עטיפות TypeScript עם ערכי ברירת מחדל, ומבטלים התנהגות undefined.
כיצד אנו מיישמים אחסון: מקרה בוחן
עבור תוסף המתרגם עם 10,000 משתמשים, תכננו מערכת אחסון: הגדרות (נושא, שפה, תרגום אוטומטי) ב-chrome.storage.sync, מטמון תרגום ב-chrome.storage.local עם פינוי LRU ב-8 MB. הנה העטיפה הטיפוסית להגדרות:
// storage/store.ts
type Settings = {
theme: 'light' | 'dark' | 'system';
targetLang: string;
autoTranslate: boolean;
ignoredDomains: string[];
};
const defaultSettings: Settings = {
theme: 'system',
targetLang: 'ru',
autoTranslate: false,
ignoredDomains: [],
};
export const settingsStore = {
async get(): Promise<Settings> {
const result = await chrome.storage.sync.get('settings');
return { ...defaultSettings, ...(result.settings ?? {}) };
},
async set(partial: Partial<Settings>): Promise<void> {
const current = await this.get();
await chrome.storage.sync.set({ settings: { ...current, ...partial } });
},
async reset(): Promise<void> {
await chrome.storage.sync.set({ settings: defaultSettings });
},
onChange(callback: (newSettings: Settings) => void): void {
chrome.storage.onChanged.addListener((changes, area) => {
if (area === 'sync' && 'settings' in changes) {
callback({ ...defaultSettings, ...changes.settings.newValue });
}
});
}
};בזכות זה, התוסף שומר בצורה אמינה על בחירות המשתמש ומגיב מיידית לשינויים. המטמון הממוצע הוא 3 MB, אך יישמנו פינוי LRU: ערכים שלא נגשו אליהם במשך יותר מ-30 יום מוסרים.
למה chrome.storage אמין יותר מ-localStorage ושיטות אחרות
| מאפיין | localStorage | chrome.storage.local | chrome.storage.sync | IndexedDB |
|---|---|---|---|---|
| זמין ב-SW | לא | כן | כן | לא (דורש עטיפה) |
| סנכרון | לא | לא | כן (דרך Google) | לא |
| מגבלה | ~5-10 MB | 10 MB (עד 1 GB עם הרשאה) | 100 KB | מוגבל בדיסק |
| התראות שינוי | לא | כן (onChanged) | כן | לא |
הערה: chrome.storage הוא האפשרות היחידה עבור service workers וסנכרון. לפי התיעוד של Google, chrome.storage.sync מסנכרן נתונים אוטומטית (developer.chrome.com).
| מגבלה | storage.local | storage.sync | storage.session |
|---|---|---|---|
| ברירת מחדל | 10 MB | 100 KB | מוגבל בזיכרון |
| עם unlimitedStorage | עד 1 GB | — | — |
תהליך העבודה על התוסף שלך
- ניתוח: קביעת סוגי נתונים, נפח (אם >10 MB, צריך סנכרון?), דרישות סנכרון וצרכים לא מקוונים.
- עיצוב: בחירת שילוב אחסון (local, sync, session, IndexedDB), עיצוב עטיפות טיפוסיות, תכנון אסטרטגיית פינוי (LRU, TTL).
- יישום: כתיבת קוד TypeScript עם כיסוי מלא של בדיקות יחידה (Jest), שימוש בתבנית Repository ובמפעלים לסוגי אחסון שונים.
- בדיקות: אימות התנהגות בעת הפעלה מחדש של SW, חריגה ממגבלות, מספר כרטיסיות, כתיבות במקביל.
- פריסה: פרסום ל-Chrome Web Store עם תיעוד API מלא.
מה כלול בעבודה
- קוד אחסון מלא עם טיפוסים ועטיפות (TypeScript).
- תיעוד API וארכיטקטורה (README).
- מדריך מיגרציה מ-localStorage (אם נדרש).
- הדרכה לצוות לתחזוקה ושינויים (ייעוץ של שעה).
- אחריות: אנו תומכים בקוד במשך 3 חודשים לאחר המסירה (תיקוני באגים).
לוחות זמנים ועלות
לוחות פיתוח לאחסון: מ-3 עד 10 ימי עבודה בהתאם למורכבות (סוג אחסון יחיד לעומת שילוב). העלות מחושבת באופן אישי לאחר ניתוח דרישות. צור קשר לייעוץ חינמי והערכה ראשונית.
כיצד להבטיח סנכרון בין מכשירים?
עבור הגדרות ונתונים קטנים אחרים, השתמש ב-// storage/store.ts type Settings = { theme: 'light' | 'dark' | 'system'; targetLang: string; autoTranslate: boolean; ignoredDomains: string[]; }; const defaultSettings: Settings = { theme: 'system', targetLang: 'ru', autoTranslate: false, ignoredDomains: [], }; export const settingsStore = { async get(): Promise<Settings> { const result = await chrome.storage.sync.get('settings'); return { ...defaultSettings, ...(result.settings ?? {}) }; }, async set(partial: Partial<Settings>): Promise<void> { const current = await this.get(); await chrome.storage.sync.set({ settings: { ...current, ...partial } }); }, async reset(): Promise<void> { await chrome.storage.sync.set({ settings: defaultSettings }); }, onChange(callback: (newSettings: Settings) => void): void { chrome.storage.onChanged.addListener((changes, area) => { if (area === 'sync' && 'settings' in changes) { callback({ ...defaultSettings, ...changes.settings.newValue }); } }); } }; . המגבלה היא 100 KB בסך הכל, אך מספיקה לתצורה. בכל שינוי, הנתונים מופצים אוטומטית לכל המכשירים שבהם התוסף מותקן. עבור נתונים גדולים יותר (לדוגמה, סימניות), השתמש ב-chrome.storage.sync עם שרת סנכרון משלך או שירות ענן.
כיצד להירשם לשינויים ולהימנע מתנאי מרוץ?
השתמש באירוע chrome.storage.local. הירשם בכל ההקשרים של התוסף כדי לסנכרן ממשק משתמש ותהליכי רקע. דוגמה:
chrome.storage.onChanged.addListener((changes, areaName) => {
if (areaName !== 'sync') return;
if ('theme' in changes) {
const { newValue } = changes.theme;
applyTheme(newValue);
}
});תבנית זו מונעת תנאי מרוץ מכיוון ששינויים מעובדים ברצף.
המלצות נוספות
onChanged יכול לאחסן עד 100 KB, עם מפתח בודד שלא יעלה על 8 KB. עבור נפחים גדולים יותר, השתמש ב-chrome.storage.onChanged.addListener((changes, areaName) => { if (areaName !== 'sync') return; if ('theme' in changes) { const { newValue } = changes.theme; applyTheme(newValue); } }); או IndexedDB. כדי לנקות את כל הנתונים, קרא ל-chrome.storage.sync, אך שים לב שסנכרון מנקה נתונים בכל המכשירים. chrome.storage ממיר אובייקטים ל-JSON אוטומטית, ולכן פונקציות, undefined וסמלים אינם מותרים. עבור נתונים בינאריים, השתמש ב-IndexedDB או בהמרת base64 (שים לב למגבלות). בעדכוני תוסף, יישם גרסאות ומיגרציות — שמור את גרסת הסכמה בנפרד.
אחסון נתונים אמין הוא הבסיס לכל תוסף. הזמן פיתוח אחסון לפרויקט שלך. צור קשר לייעוץ חינמי והערכה ראשונית.







