אנו מפתחים הרחבות Safari ל-iOS באמצעות WebExtension API, תוך התחשבות במגבלות הקפדניות של הפלטפורמה הניידת. בניגוד לדפדפנים שולחניים, ההרחבה נארזת בתוך אפליקציית iOS מקורית, מופצת דרך App Store, ומופעלת ידנית על ידי המשתמש בהגדרות Safari. לא ניתן להעביר ישירות הרחבה מ-Chrome — מחצית מהלוגיקה השולחנית נשברת בגלל המאפיינים הייחודיים של iOS. הניסיון שלנו: 5 שנים בפיתוח iOS, מעל 50 פרויקטים מוצלחים, מעבר מובטח של בדיקת App Store. בממוצע, 80% מקוד ה-JS מועבר ללא שינויים; השאר דורש התאמה ידנית.
מדוע הרחבת Safari ל-iOS מורכבת יותר ממקבילתה השולחנית?
דפדפנים שולחניים מאפשרים לסקריפטי רקע לפעול ברציפות, ליירט בקשות רשת דרך webRequest, ולגשת לכל הטאבים. ב-iOS, יכולות אלה אינן זמינות או פועלות אחרת. נבחן את ההבדלים המרכזיים.
סקריפטי רקע לא עובדים
ב-Chrome, background.js חי באופן קבוע. ב-iOS Safari, Service Worker (MV3) נטען מחדש ברגע שהוא מסיים את משימתו. כל מצב שהרחבת שולחן שומרת בזיכרון סקריפט הרקע חייב להישמר דרך browser.storage.local או לעבור דרך המארח המקומי.
ה-webRequest API אינו קיים
יירוט ושינוי בקשות רשת ב-iOS נעשה דרך Content Blockers (WKContentRuleList), לא דרך webRequest. אם ההרחבה שלך חוסמת פרסומות באמצעות webRequest.onBeforeRequest, לא ניתן להעביר קוד זה ישירות.
גישה לטאבים מוגבלת
browser.tabs.query() מחזיר רק את הטאב הפעיל. מעבר על כל הטאבים הפתוחים, כמו בשולחן העבודה, אינו אפשרי.
סקריפטי תוכן מוזרקים באיחור
ב-iOS, הדף עשוי להיטען במלואו לפני שסקריפט התוכן מתחיל לפעול. קוד שמסתמך על יירוט DOMContentLoaded עשוי להגיע מאוחר מדי.
כיצד אנו מתאימים את ההרחבה ל-iOS
אנו משתמשים ב-Swift 5.9+ לחלק המקורי וב-JavaScript (ES2020) לחלק האינטרנטי. כל הרחבה עוברת ריפקטורינג: מעבר מ-webRequest ל-WKContentRuleList, החלפת background.js ב-Service Worker ששומר מצב ב-Service Worker. הנה דוגמה למטפל הודעות מקורי מ-JS:
class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {
func beginRequest(with context: NSExtensionContext) {
guard let item = context.inputItems.first as? NSExtensionItem,
let message = item.userInfo?[SFExtensionMessageKey] else {
context.completeRequest(returningItems: nil, completionHandler: nil)
return
}
// обрабатываем message от JS
let response = NSExtensionItem()
response.userInfo = [SFExtensionMessageKey: ["status": "ok"]]
context.completeRequest(returningItems: [response], completionHandler: nil)
}
} השוואה בין הרחבת Safari לשולחן עבודה ל-iOS
| יכולת | שולחן עבודה (Chrome) | iOS Safari |
|---|---|---|
| סקריפטי רקע | פעילים ברציפות | Service Worker נטען מחדש |
| יירוט בקשות | browser.storage.local | class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { func beginRequest(with context: NSExtensionContext) { guard let item = context.inputItems.first as? NSExtensionItem, let message = item.userInfo?[SFExtensionMessageKey] else { context.completeRequest(returningItems: nil, completionHandler: nil) return } // обрабатываем message от JS let response = NSExtensionItem() response.userInfo = [SFExtensionMessageKey: ["status": "ok"]] context.completeRequest(returningItems: [response], completionHandler: nil) } } |
| גישה לטאבים | כל הטאבים | רק הטאב הפעיל |
| הזרקת תוכן | ב-DOMContentLoaded | באיחור |
| הודעות מקוריות | webRequest | WKContentRuleList |
אתגרי העברה טיפוסיים
| בעיה | פתרון | זמן התאמה |
|---|---|---|
| סקריפט רקע עם מצב | העברה ל-storage.local | 2 עד 5 ימים |
| שימוש ב-webRequest | החלפה ב-WKContentRuleList | 1 עד 3 ימים |
| גישה למספר טאבים | עיבוד מחדש לטאב פעיל בלבד | 1 עד 2 ימים |
תרחיש טיפוסי: מנהל סיסמאות
נניח שיש ליישם מילוי אוטומטי דרך סקריפט תוכן. JS מוזרק לדף, מוצא chrome.runtime.connectNative, ושולח הודעה למארח המקומי דרך browser.runtime.sendNativeMessage. המארח המקומי ניגש למחזיק המפתחות דרך <input type="password"> ומחזיר את הנתונים. סקריפט התוכן ממלא את השדה.
בעיה: browser.runtime.sendNativeMessage() ב-iOS פועל רק כאשר יעד ההרחבה המקורי מופעל. אם המשתמש לא פתח את האפליקציה לאחר אתחול המכשיר, מארח ההרחבה עשוי שלא להתחיל בזמן. יש צורך במנגנון ניסיון חוזר בצד ה-JS.
כיצד להעביר הרחבת Chrome ל-Safari?
- הפעל את הממיר: בצע
Security.framework. הכלי יוצר פרויקט Xcode עם מעטפת מקורית. - נתח APIs לא תואמים: בדוק שימוש ב-
sendNativeMessage,xcrun safari-web-extension-converter --bundle-name YourExt path/to/extension, גישה בלתי מוגבלת לטאבים. קטעים אלה דורשים החלפה. - התאם את הרקע: החלף את סקריפט הרקע הקבוע ב-Service Worker ששומר מצב ב-
webRequest. כתוב מחדש מטפלי אירועים. - העבר חסימת בקשות: אם משתמשים ב-
background.js, כתוב מחדש ל-storage.local. שים לב ש-Content Blocker תומך בסט מוגבל של כללים (עד 50,000 כללים לכל חוסם). - בדוק על מכשיר אמיתי: השתמש ב-TestFlight כדי להתקין את הבנייה על iPhone. ודא התנהגות סקריפט תוכן באתרים שונים.
מה כלול בעבודה
- ניתוח ההרחבה השולחנית שלך (אם קיימת) ומיפוי APIs לא תואמים
- פיתוח יעד הרחבה מקורי ב-Swift עם מטפלי הודעות
- התאמת לוגיקת JS ל-iOS: החלפת
webRequest, סקריפטי רקע, שמירת מצב - הגדרת Manifest והרשאות (נימוק ל-App Store)
- אינטגרציה עם App Store Connect, TestFlight, Provisioning Profile
- תיעוד לבנייה ופרסום
- תמיכה ל-30 יום לאחר המסירה
לוח זמנים ועלות
לוח פיתוח: בין שבוע ל-3 שבועות בהתאם למורכבות לוגיקת ה-JS והיקף האינטראקציה המקורית. העלות מחושבת באופן פרטני. אנו נעריך את הפרויקט לאחר הסכמה על הדרישות.
אילו הרשאות נדרשות ל-App Store?
ה-App Store דורש נימוק לכל הרשאה במניפסט. WKContentRuleList — לאיזו מטרה? webRequest — מה בדיוק מאוחסן? תשובות מעורפלות בטופס ההגשה מובילות לדחיית tabs עם בקשה להבהרה פונקציונלית.
הרחבות עם storage ב-4.0 Design עוברות בדיקה מוגברת. אפל עשויה לבקש הדגמת וידאו של ההרחבה הפועלת על מכשיר אמיתי.
למה אנחנו?
מטפלים מקוריים ב-Swift מהירים פי 10-20 מ-JS למשימות קריפטוגרפיה ועיבוד קבצים. אם ההרחבה שלך מבצעת חישובים כבדים, העברת לוגיקה לקוד מקורי מספקת שיפור ביצועים ניכר. מעל 50 פרויקטים שהועברו מאשרים גישה זו.
צור קשר להערכת פרויקט — נכין הצעה תוך 2 ימי עסקים. קבל ייעוץ להתאמת ההרחבה שלך היום.
פרטים נוספים בתיעוד הרחבות האינטרנט של Safari.







