Chrome vs. Firefox vs. Edge vs. Safari: Bericht aus 9 Erweiterungen Skip to content

Wissen

Praktisches Know-how zu Frontend, KI-Tools und Softwareentwicklung.

Chrome vs. Firefox vs. Edge vs. Safari: Was wir aus der Veröffentlichung von 9 Browser-Erweiterungen gelernt haben

Veröffentlicht: 17 Min. Lesezeit POLPROG Browser Extensions

Neun Erweiterungen, vier Browser und deutlich mehr als eine `manifest.json`. Wir zeigen, wo gemeinsam genutzter Code wirklich endet, warum Safari einen eigenen Prozess benötigt und welche Fehler erst Firefox und die Erweiterungs-Stores sichtbar machen.

Auf dem Papier sollte eine moderne Browser-Erweiterung beinahe automatisch ein plattformübergreifendes Produkt sein. Chrome, Firefox, Edge und Safari unterstützen WebExtensions, verwenden eine ähnliche manifest.json und stellen vergleichbare Mechanismen bereit: Content Scripts, Storage, Kommunikation zwischen Kontexten, eine Schaltfläche in der Symbolleiste und Einstellungsseiten.

Das stimmt, aber nur bis zu einem gewissen Punkt.

Nach der Veröffentlichung und Portierung von neun POLPROG-Erweiterungen wissen wir: Gemeinsamer Code bedeutet nicht automatisch ein gemeinsames Produkt. Der Großteil der Geschäftslogik lässt sich teilen, doch Browserverhalten, Lebenszyklus des Hintergrundprozesses, Benutzeroberfläche, Berechtigungen, Paketierung und Store-Prüfung bleiben eigenständige Probleme.

Zum Portfolio gehören:

  • AutoScroll,
  • ClickClean,
  • DevScope,
  • LeakLens,
  • LoopIt,
  • Loudly,
  • OneMoreJump,
  • TabZoo,
  • TubePilot.

Es handelt sich nicht um neun Kopien desselben Add-on-Typs. Die Gruppe umfasst Werkzeuge für Video, Audioverstärkung, Datenschutz, Datenbereinigung, Entwicklung, Tab-Verwaltung sowie ein leichtgewichtiges Spiel. Entsprechend beschränkten sich die Probleme nicht auf eine einzelne API. Sie betrafen Service Worker, Pop-ups, Content Scripts, Audio, Storage, Icons, Berechtigungen und den Veröffentlichungsprozess.

POLPROG betreut öffentlich neun Erweiterungsprodukte, die zunächst vor allem für Chrome und Firefox veröffentlicht wurden. Spätere Portierungen umfassten auch Edge und Safari. [1][2]

Dieser Artikel ist kein Labor-Benchmark. Wir haben nicht ab dem ersten Commit jede Minute pro Store gemessen. Deshalb behaupten wir weder, dass Safari exakt 2,7-mal so teuer wie Chrome sei, noch dass 94 % des Codes gemeinsam genutzt würden. Das wäre nur scheinbare Präzision.

Wir können jedoch etwas Nützlicheres zeigen: Welche Annahmen sich als falsch erwiesen haben, wo reale Fehler auftraten und wie wir den gesamten Prozess heute von Grund auf aufbauen würden.

Quellen zuletzt geprüft: 17. Juli 2026.

Vier Browser, vier unterschiedliche Rollen

PlattformRolle in unserem ProzessGrößter VorteilHäufigste Falle
ChromeHauptreferenz für Manifest-V3-KompatibilitätUmfangreichste Dokumentation und größter ErweiterungsmarktSuspendierter Service Worker und strenge Berechtigungsanforderungen
EdgeChromium-basierte PortierungGeringe Codeabweichung gegenüber ChromeEigenes Partner Center, eigene Metadaten und Zertifizierung
FirefoxUnabhängige WebExtensions-ImplementierungDeckt Chromium-abhängige Annahmen sehr gut aufUnterschiede bei API und Manifest, Signierung und Quellcodeanforderungen
SafariEigenständiges Produkt im Apple-ÖkosystemZugang zu Nutzern von macOS, iOS und iPadOSXcode, Container-App, Signierung und anderes Laufzeitverhalten

MDN betont, dass WebExtensions Add-ons nach möglichst kleinen Änderungen in den wichtigsten Browsern lauffähig machen soll. Gleichzeitig dokumentiert MDN wichtige Unterschiede zwischen Chrome, Firefox und Safari bei API-Verfügbarkeit, Manifesten und asynchronen Operationen. [7][8]

Das entspricht unserer Erfahrung. „Kleine Änderungen“ sind bei einem einfachen Add-on realistisch. Je stärker eine Erweiterung mit Seite, Medien, Tab-Lebenszyklus oder Hintergrundprozess interagiert, desto weniger hilfreich wird das Wort „klein“.

Lektion 1: Eine Codebasis ja, ein Manifest nicht unbedingt

Der beste Ausgangspunkt ist gemeinsame Logik mit getrennten Build-Konfigurationen.

In der Praxis hat sich eine Struktur bewährt, in der Folgendes gemeinsam genutzt wird:

  • Funktionslogik,
  • Datenmodelle,
  • Storage-Module,
  • Validierung,
  • der Großteil von Pop-up- und Einstellungsoberfläche,
  • Lokalisierungen,
  • Unit-Tests.

Getrennt bleiben dagegen:

  • Manifest-Varianten,
  • Erweiterungskennungen,
  • minimale Browserversionen,
  • Hintergrundkonfiguration,
  • ein Teil der Berechtigungen,
  • Icons und Store-Assets,
  • Paketierung,
  • Signierung,
  • Veröffentlichungsskripte.

Das bedeutet nicht, vier manuell kopierte Verzeichnisse zu pflegen. Das führt schnell zu Abweichungen. Besser ist gemeinsamer Quellcode plus Generator oder Konfigurationsschicht, die für jede Plattform ein eigenes Artefakt erzeugt.

Firefox benötigt beispielsweise eigene Einstellungen unter browser_specific_settings. Bei Manifest V3 ist eine Erweiterungs-ID für die Signierung notwendig. Seit November 2025 müssen neue bei AMO eingereichte Add-ons zudem Angaben zur Datenerfassung deklarieren. [9]

Safari benötigt dagegen ein Xcode-Projekt und eine App, die die Erweiterung enthält. Apple stellt einen WebExtension-Konverter bereit, doch das Ergebnis muss weiterhin wie ein natives Projekt behandelt werden, das signiert und über den App Store verteilt wird. [3][4]

Ein gemeinsames Manifest wäre daher eine künstliche Ersparnis. Einige kleine, explizite Unterschiede sind leichter zu pflegen als eine einzige Datei voller Ausnahmen und Bedingungen.

Lektion 2: Manifest V3 hat das Browserverhalten nicht vereinheitlicht

Manifest V3 hat einen Teil der Kompatibilität verbessert und das Erweiterungsmodell geordnet, aber keine einheitliche Laufzeit geschaffen.

Die sichtbarste Änderung in Chrome ist der Ersatz dauerhaft laufender Background Pages durch einen Extension Service Worker. Google beschreibt ihn als zentralen Ereignis-Handler, der bei Bedarf gestartet wird. Der Prozess kann beendet werden, und ausschließlich im Arbeitsspeicher gehaltene Variablen verschwinden mit ihm. [5][6]

Das hat direkte Konsequenzen.

Code wie:

let activeSessions = new Map();
let currentTab = null;
let isEnabled = false;

kann nicht die einzige Quelle der Wahrheit sein, wenn die Daten nach einem Neustart des Service Workers wieder benötigt werden.

Zustand sollte in drei Gruppen aufgeteilt werden:

  1. kurzfristiger Zustand, der sicher verschwinden darf;
  2. aus aktiven Tabs oder dem DOM rekonstruierbarer Zustand;
  3. dauerhafter Zustand, der in storage.local, storage.session oder an einem anderen geeigneten Ort gespeichert werden muss.

Ebenso wichtig ist die Registrierung von Listenern. Chrome empfiehlt, Event Handler im globalen Bereich des Skripts zu deklarieren, damit sie beim Aufwecken des Service Workers synchron registriert werden. Ein Listener, der erst nach asynchroner Initialisierung entsteht, kann genau das Ereignis verpassen, das den Worker aufgeweckt hat. [10]

In Entwicklungstests ist das leicht zu übersehen. Geöffnete DevTools können den Lebenszyklus des Service Workers beeinflussen, während der Fehler erst bei normaler Nutzung auftritt. Google beschrieb ähnliche Probleme in einer Analyse von MV3-Migrationen: Das Suspendieren des Prozesses kann Timer unterbrechen und im Speicher gehaltenen Zustand entfernen. [11]

Die wichtigste Regel lautet daher:

Der Hintergrundprozess einer Erweiterung sollte wie ein unterbrechbarer Ereignis-Handler entworfen werden, nicht wie ein kleiner Node.js-Server, der permanent läuft.

Lektion 3: Chrome ist ein guter Startpunkt, aber ein schlechtes einziges Testumfeld

Chrome ist die natürliche Basis für ein Manifest-V3-Projekt. Es bietet umfangreiche Dokumentation, Beispiele, Entwicklerwerkzeuge und das größte Add-on-Ökosystem.

Gleichzeitig erzeugt ausschließliches Testen in Chrome ein falsches Sicherheitsgefühl.

Wenn Code in Chrome und Edge funktioniert, bestätigt das vor allem die Kompatibilität mit Chromium. Es bestätigt nicht:

  • korrektes Verhalten in Gecko,
  • korrektes Verhalten in WebKit,
  • Robustheit gegenüber einem anderen Pop-up-Lebenszyklus,
  • Funktion unter einem anderen Berechtigungsmodell,
  • korrekte Icon-Skalierung,
  • korrektes Audioverhalten,
  • identische Semantik der API.

Der Chrome Web Store verlangt einen einzigen, engen und leicht verständlichen Zweck. Er verlangt zudem den minimalen Berechtigungssatz, eine Begründung für jede Berechtigung und konsistente Angaben zur Datennutzung. Zu weitreichende Berechtigungen können zu einer Ablehnung führen. In Manifest V3 darf außerdem kein entfernt gehosteter Code geladen und ausgeführt werden. [12]

Diese Anforderungen beeinflussen die Architektur früher, als man zunächst denkt. Zugriff auf alle Websites „auf Vorrat“ hinzuzufügen, ist nicht neutral. Er muss später gegenüber Prüfer und Nutzer begründet werden. Besser können activeTab, optionale Host-Berechtigungen oder auf konkrete Domains beschränkter Zugriff sein.

Chrome hat uns daher zwei gegensätzliche Dinge gelehrt:

  • Es eignet sich gut, um die grundlegende MV3-Variante festzulegen.
  • Es sollte nicht alle Annahmen der gemeinsamen Schicht bestimmen.

Lektion 4: Edge ist die einfachste technische Portierung, aber kein kostenloser Vertriebskanal

Microsoft beschreibt die Portierung einer vorhandenen Chrome-Erweiterung zu Edge offiziell als eigenen, unterstützten Ablauf. Da beide Browser Chromium verwenden, sind Unterschiede im Kerncode häufig gering. [13]

In unseren Projekten erforderte Edge meist die wenigsten technischen Änderungen. Das bedeutete trotzdem keine Veröffentlichung „mit einem Klick“.

Die Erweiterung gelangt in ein separates Partner Center. Dort muss man:

  • ein eigenes ZIP-Paket hochladen,
  • Verfügbarkeit und Märkte festlegen,
  • eine Kategorie auswählen,
  • den einzelnen Zweck beschreiben,
  • jede Berechtigung begründen,
  • die Nutzung entfernten Codes deklarieren,
  • Datenpraktiken beschreiben,
  • Listings für mehrere Sprachen vorbereiten,
  • separate Grafiken und Screenshots hochladen,
  • Hinweise für das Zertifizierungsteam hinzufügen. [14]

Wie Google verlangt auch Microsoft einen klar definierten Zweck und den kleinstmöglichen Berechtigungssatz. Partner Center weist außerdem darauf hin, dass unvollständige oder widersprüchliche Angaben die Zertifizierung verlängern oder zu einer Ablehnung führen können. [14]

Edge zeigt damit gut den Unterschied zwischen Portierungskosten und Kanalkosten.

Der Code kann nahezu identisch sein, dennoch müssen gepflegt werden:

  • ein separater Produkteintrag,
  • ein separater Prüfstatus,
  • separate Metadaten,
  • separate Grafikvarianten,
  • ein eigener Aktualisierungsprozess,
  • konsistente Datenschutzerklärungen.

Bei einer Erweiterung ist dieser Aufwand überschaubar. Bei neun Produkten wird daraus ein regelmäßiger operativer Prozess.

Lektion 5: Firefox erkennt am besten Code, der „versehentlich nur für Chrome“ geschrieben wurde

Firefox verwendet WebExtensions, ist aber kein Chromium. Genau deshalb ist er als Testumgebung so wertvoll.

Der bekannteste Unterschied betrifft Namespace und asynchronen Code. Chrome verwendete historisch chrome und Callbacks, Firefox und Safari dagegen browser und Promises. In Manifest V3 haben Chrome und Edge bei vielen Methoden Promise-Unterstützung ergänzt, aber nicht jede Differenz ist verschwunden. Mozilla empfiehlt, mit browser und Promises zu arbeiten und bei Bedarf das WebExtension Browser API Polyfill einzusetzen. [8][15]

Es lohnt sich nicht, Bedingungen wie:

if (isFirefox) {
  // ...
} else {
  // ...
}

über jedes API-Calling zu verteilen. Besser ist eine kleine Adapter-Schicht:

export const extensionApi = {
  storageGet: (keys) => browser.storage.local.get(keys),
  storageSet: (value) => browser.storage.local.set(value),
  sendMessage: (message) => browser.runtime.sendMessage(message),
};

und die Unterschiede an einer Stelle zu lösen.

Firefox erzwingt außerdem mehr Disziplin bei der Veröffentlichung. Erweiterungen müssen signiert sein, selbst wenn sie in der Standardkonfiguration unabhängig verteilt werden. AMO validiert das Paket, und minifizierter oder schwer lesbarer Code kann die Einreichung des vollständigen Quellpakets erfordern. Mozilla kann auch nach der Veröffentlichung eine manuelle Prüfung durchführen und die aktuelle oder eine frühere Version ablehnen. [16][17][18]

Aus Qualitätssicht ist das ein Vorteil. Der Prozess zwingt dazu, dass der Build:

  • reproduzierbar,
  • dokumentiert,
  • frei von unnötiger Obfuskation,
  • mit dem deklarierten Verhalten konsistent,
  • ohne internes Wissen des Autors prüfbar ist.

Firefox deckte außerdem Probleme an Stellen auf, an denen Chromium toleranter war. Dazu gehörten Nachrichtenverarbeitung, Warten auf Promise-Antworten, Unterschiede bei Pop-ups und Annahmen über das Vorhandensein einzelner API-Eigenschaften.

Die wichtigste Lektion:

Firefox ist kein zusätzlicher Haken nach Projektabschluss. Er ist eine zweite unabhängige Laufzeit, die früh in die Tests aufgenommen werden sollte.

Lektion 6: Safari ist keine Store-Portierung, sondern eine eigene Produktphase

Apple unterstützt WebExtensions und stellt ein Tool zur Konvertierung aus Chrome, Firefox oder Edge bereit. Trotzdem ist der Safari-Prozess grundlegend anders. [3][4]

Die Erweiterung wird Teil einer in Xcode erstellten Anwendung. Verwalten muss man:

  • das App-Projekt,
  • das Erweiterungs-Target,
  • die Bundle-ID der App,
  • eine eigene Bundle-ID der Erweiterung,
  • Signierung,
  • Profile und Zertifikate,
  • das App-Icon,
  • Entitlements,
  • Archivierung,
  • App Store Connect,
  • App-Store-Prüfung.

Apple verlangt, dass die Erweiterung mit der aktuellen Safari-Version des jeweiligen Systems funktioniert, die Safari-Oberfläche nicht stört und nicht mehr Website-Zugriff anfordert als nötig. [19]

Hier traten die konkretesten Probleme unseres Portfolios auf.

Loudly: Die Oberfläche funktionierte, aber der Ton wurde nicht verstärkt

Loudly verändert den auf einer Webseite abgespielten Ton. In der Safari-Version ließ sich die Oberfläche anzeigen, Einstellungen konnten geändert werden und das Produkt wirkte funktionsfähig. Das tatsächliche Audiosignal wurde jedoch nicht verstärkt.

Das ist eine problematischere Fehlerklasse als ein offensichtlicher Absturz. Der Smoke Test „Pop-up öffnet sich“ besteht, aber das zentrale Produktversprechen wird nicht erfüllt.

Schlussfolgerung: Bei Multimedia-Erweiterungen muss der Funktionstest das Endergebnis messen, nicht nur den Zustand der Oberfläche.

TabZoo: Weiße Seite statt Anwendung

Die Safari-Version von TabZoo konnte eine leere weiße Seite anzeigen. Ursache können ein Initialisierungsfehler, Asset-Pfade, ein falscher Kontext oder eine Ausnahme vor dem Rendern sein.

In Chromium kann derselbe Fehler verborgen bleiben, wenn Startreihenfolge oder API-Verfügbarkeit anders sind.

Schlussfolgerung: Jede Ansicht einer Erweiterung sollte einen minimalen Diagnosemechanismus und Fehlerbehandlung für die Initialisierung besitzen. Eine leere Seite darf kein endgültiger Produktzustand sein.

LoopIt: Ein Klick öffnete zwei Oberflächen

In LoopIt führte ein Klick auf das Icon in Safari dazu, dass ein Pop-up und zusätzlich ein Erweiterungspanel erschienen. Das war ein Konflikt zwischen deklarativ konfiguriertem Pop-up und manueller Klickbehandlung.

In einem Browser wirkte das Verhalten korrekt, in einem anderen entstand eine doppelte Reaktion.

Schlussfolgerung: Es muss eindeutig festgelegt werden, wer den Klick auf die Schaltfläche besitzt. Entweder hat sie ein default_popup, oder das Ereignis wird programmatisch verarbeitet. Beide Mechanismen zu kombinieren, erfordert sehr bewusstes Design.

Diese drei Fälle zeigen, warum der Apple-Konverter die Portierung nicht abschließt. Der Konverter überträgt Struktur. Er bestätigt nicht die Semantik des Verhaltens.

Lektion 7: Video- und Audio-Erweiterungen sind schwieriger, als das Pop-up vermuten lässt

Vier unserer Produkte hängen stark von Medien ab:

  • AutoScroll,
  • LoopIt,
  • Loudly,
  • TubePilot.

Jedes muss mehrere Welten koordinieren:

  • das DOM der Seite,
  • das Audio- oder Videoelement,
  • den Content Script,
  • das Pop-up,
  • den Hintergrundprozess,
  • gespeicherte Einstellungen,
  • SPA-Navigation,
  • Wechsel des aktiven Tabs.

Die meisten Fehler entstehen nicht in einer einzelnen Funktion, sondern an den Grenzen zwischen diesen Kontexten.

Ein Beispielszenario:

  1. Der Nutzer öffnet das Pop-up.
  2. Das Pop-up fragt den Content Script nach dem aktuellen Zustand.
  3. Die Seite hat gerade das Video ohne vollständiges Neuladen gewechselt.
  4. Das alte Videoelement wurde entfernt.
  5. Der Content Script hält noch eine Referenz auf das vorherige Element.
  6. Das Pop-up zeigt einen korrekten Wert, verändert aber einen inaktiven Player.

Ein weiteres setTimeout ist keine Lösung. Nötig ist ein explizites Zustandsmodell:

  • aktives Element identifizieren,
  • DOM-Änderungen beobachten,
  • Handler erneut verbinden,
  • Ausführung des Befehls bestätigen,
  • UI erst nach einer Antwort synchronisieren,
  • Zustand nach Neustart des Hintergrundprozesses wiederherstellen.

Bei Diensten wie YouTube muss zusätzlich SPA-Navigation berücksichtigt werden. Ein Video-Wechsel lädt nicht immer das gesamte Dokument neu, daher reicht eine einmalige Initialisierung des Content Scripts nicht aus.

Lektion 8: Icon und Pop-up sind Teil der Implementierung, nicht nur des Brandings

Ein plattformübergreifender Build kann technisch korrekt sein und dennoch falsch aussehen.

In unseren Tests erschienen Icons:

  • zu groß für die verfügbare Fläche,
  • ohne Sicherheitsabstand,
  • an den Rändern anliegend,
  • optisch kleiner als andere Erweiterungsicons trotz identischer Dateigröße,
  • im Store korrekt, aber in der Browser-Symbolleiste kaum lesbar.

Die PNG-Abmessungen lösen das Problem nicht. Entscheidend ist die visuelle Größe des Symbols innerhalb der Fläche.

Dasselbe gilt für Pop-ups. Dieselbe CSS-Breite kann unterschiedlich dargestellt werden aufgrund von:

  • Font-Rendering,
  • Standardstilen von Formularfeldern,
  • Scrollbar-Verhalten,
  • Höhenberechnung,
  • Systemrändern,
  • Display-Skalierung,
  • Hell- und Dunkelmodus.

Deshalb bereiten wir Assets heute als Set vor, nicht als einzelnes Bild:

  • Quell-SVG,
  • vom Manifest verlangte Rastervarianten,
  • kontrollierte Safe Area,
  • Safari-App-Icon,
  • Listing-Grafiken,
  • Store-Screenshots.

Die Erweiterungsoberfläche sollte zudem minimale und maximale Maße besitzen und bei längeren Übersetzungen lesbar bleiben.

Lektion 9: Veröffentlichung ist ein eigenes operatives Produkt

Der größte organisatorische Fehler wäre die Annahme, dass die Arbeit nach der Erzeugung der ZIP-Datei endet.

Jeder Store besitzt ein eigenes Vertrauensmodell.

Chrome Web Store

Chrome verlangt einen klaren, einzelnen Zweck, minimale Berechtigungen, Angaben zur Datennutzung und eine Datenschutzrichtlinie. Remote ausgeführter Code ist in Manifest V3 verboten. [12]

Die Produktbeschreibung muss dem tatsächlichen Verhalten entsprechen. Wenn das Listing eine Funktion verspricht, die der Prüfer nicht ausführen kann, ist das kein Marketingproblem, sondern ein Zertifizierungsproblem.

Firefox Add-ons

AMO validiert das Paket automatisch, kann Quellcode für gebauten Code verlangen und behält die Möglichkeit einer späteren manuellen Prüfung. Sicherheits- und Datenschutzhinweise sollten auch dann behoben werden, wenn man technisch fortfahren könnte. [16][17]

Microsoft Edge Add-ons

Partner Center verlangt separate Angaben zu Verfügbarkeit, Datenschutz und Sprach-Listings. Jede Berechtigung sollte begründet werden, und die Informationen müssen mit Manifest und Verhalten übereinstimmen. [14]

Safari und App Store

Safari ergänzt eine App-Schicht, Signierung, App-Store-Metadaten und die für Apple-Apps geltenden Richtlinien. Die Erweiterung muss mit der aktuellen Safari-Version funktionieren und den Website-Zugriff auf das notwendige Minimum begrenzen. [19]

Neun Erweiterungen bedeuten daher nicht neun Listings. Bei vollständiger Abdeckung von vier Plattformen entstehen bis zu 36 Produkt-Browser-Kombinationen, noch ohne Sprachversionen und separate Varianten für Apple-Geräte.

Das ist Grund genug, Metadaten im Repository zu halten.

Lektion 10: Man braucht eine Testmatrix, keine Notiz „Erweiterung prüfen“

Für jede Erweiterung pflegen wir denselben Testkern und ergänzen anschließend funktionsspezifische Fälle.

Minimaler Smoke Test

Nach jedem Build prüfen wir:

  1. saubere Installation;
  2. Aktualisierung von der vorherigen Version;
  3. Anzeige des Icons;
  4. Öffnen des Pop-ups;
  5. keine Fehler bei der Initialisierung;
  6. Speichern und erneutes Lesen der Einstellungen;
  7. Funktion nach Schließen und Neustart des Browsers;
  8. Funktion nach Suspendierung des Hintergrundprozesses;
  9. Verhalten ohne Berechtigung für die Seite;
  10. Verhalten auf einer nicht unterstützten Seite.

Kommunikationstest

Separat testen wir:

  • Pop-up → Background,
  • Pop-up → Content Script,
  • Content Script → Background,
  • asynchrone Antwort,
  • kein aktiver Tab,
  • Neuladen des Tabs,
  • SPA-Navigation,
  • erneute Injektion des Content Scripts,
  • Schließen des Pop-ups vor Eingang der Antwort.

Funktionsspezifischer Test

Bei Loudly reicht es nicht, den Regler zu bewegen. Die Änderung des Audiopegels muss bestätigt werden.

Bei LoopIt muss geprüft werden, ob die Wiedergabe tatsächlich in den gewählten Bereich zurückkehrt.

Bei AutoScroll müssen unterschiedliche Layouts, Vollbildmodus, Video-Wechsel und manuelles Scrollen getestet werden.

Bei ClickClean muss der tatsächliche Effekt auf vorbereiteten Testdaten geprüft werden, nicht nur die Meldung „Fertig“.

Bei DevScope und LeakLens muss der Bericht auf Seiten mit unterschiedlichen CSP-Regeln, Frame-Anzahlen und Header-Sätzen überprüft werden.

Plattformtest

Am Ende kommen browserbezogene Fälle hinzu:

  • Neustart des Service Workers in Chromium,
  • signiertes Firefox-Paket,
  • Host-Berechtigungen in Firefox,
  • Installation und Aktivierung der Erweiterung in Safari,
  • macOS- und iOS-Versionen, sofern unterstützt,
  • Aktualisierung über den Store statt nur lokales Sideloading.

Lektion 11: Automatisierte Tests ersetzen keine echte Browser-QA

Automatisierung ist notwendig, hat aber Grenzen.

Unit-Tests eignen sich gut für:

  • Geschäftslogik,
  • Validierung,
  • Storage-Migrationen,
  • Datenformatierung,
  • Regeln zur Aktivierung von Funktionen.

Integrationstests können prüfen:

  • das Manifest,
  • Vorhandensein von Dateien,
  • Kommunikation zwischen Modulen,
  • grundlegende API-Aufrufe,
  • Vollständigkeit der Lokalisierung.

E2E-Tests in Chromium erkennen einen großen Teil der UI- und Content-Script-Regressionen.

Sie bestätigen jedoch nicht, dass:

  • Firefox alle Berechtigungen identisch interpretiert,
  • Safari Audio korrekt verändert,
  • der App Store das richtige Target startet,
  • das Pop-up nicht doppelt geöffnet wird,
  • das Icon in der Systemsymbolleiste korrekt aussieht.

Die teuersten Fehler unserer Portierungen waren nicht solche, die sich leicht mit Unit-Tests finden ließen. Es waren Integrationsfehler zwischen Erweiterung, Browser, Webseite und Betriebssystem.

Lektion 12: Die Kompatibilitätsschicht sollte Fähigkeiten beschreiben, nicht Browsernamen

Am Anfang eines Projekts ist eine Bedingung wie diese verlockend:

if (browserName === "safari") {
  // spezielles Verhalten
}

Manchmal ist sie unvermeidbar, sollte aber nicht das grundlegende Architekturmodell sein.

Bessere Fragen sind:

  • Unterstützt die Umgebung die jeweilige API?
  • Ist das Pop-up deklarativ?
  • Ist der Hintergrund ein Service Worker?
  • Ist eine bestimmte Methode verfügbar?
  • Benötigt die Funktion einen nativen Container?
  • Stellt die Seite das benötigte Medienelement bereit?

Fähigkeitsbasierter Code ist robuster gegenüber Versionsänderungen und leichter zu testen.

Eine Plattformschicht kann zum Beispiel Folgendes bereitstellen:

export const capabilities = {
  supportsSessionStorage: Boolean(browser.storage?.session),
  supportsSidePanel: Boolean(browser.sidePanel),
  usesServiceWorker: import.meta.env.BACKGROUND_MODE === "service-worker",
  isSafariContainer: import.meta.env.TARGET === "safari",
};

Das beseitigt Unterschiede nicht. Es macht sie explizit und konzentriert sie an einer Stelle.

Lektion 13: Privacy-first vereinfacht die Veröffentlichung tatsächlich

POLPROG-Erweiterungen werden ohne Analytics, Tracking und externes Backend entwickelt, wenn diese nicht benötigt werden.

Das ist nicht nur eine Markenentscheidung. Es vereinfacht:

  • Beschreibung der Datenflüsse,
  • Datenschutzrichtlinie,
  • Begründung von Berechtigungen,
  • Code Review,
  • Risiko eines Datenlecks,
  • Konsistenz zwischen Listing und Code.

Das bedeutet nicht, dass eine datenschutzfreundliche Erweiterung keine Dokumentation benötigt. Wenn ein Add-on Seiteninhalte, Verlauf, Tabs oder Cookies liest, muss klar erklärt werden, warum, selbst wenn nichts an einen Server gesendet wird.

Chrome und Edge verlangen Begründungen für Berechtigungen und Angaben zur Datennutzung. Firefox verlangt bei neuen Add-ons Informationen zu Berechtigungen im Zusammenhang mit Datenerfassung. Safari empfiehlt, Website-Zugriff auf das notwendige Minimum zu beschränken. [9][12][14][19]

Von Anfang an mit minimalen Berechtigungen zu entwerfen, ist deutlich einfacher, als überflüssige Rechte nach einer Ablehnung zu entfernen.

Lektion 14: Die Release-Pipeline sollte Produkte bauen, nicht ein Archiv namens final-final.zip

Bei neun Erweiterungen ist manuelles Paketieren schnell nicht mehr sicher.

Eine gute Pipeline sollte:

  1. die Version prüfen;
  2. das Basis-Manifest validieren;
  3. das plattformspezifische Manifest generieren;
  4. den Code bauen;
  5. die richtigen Icons kopieren;
  6. nach Remote-Code prüfen;
  7. Tests ausführen;
  8. getrennte Artefakte erzeugen;
  9. Prüfsummen erstellen;
  10. Changelog und Store-Informationen vorbereiten.

Beispielausgabe:

dist/
  loudly/
    chrome/loudly-1.4.0.zip
    edge/loudly-1.4.0.zip
    firefox/loudly-1.4.0.xpi
    safari/Loudly.xcarchive

Die Version sollte aus einer einzigen Quelle der Wahrheit stammen, die Artefakte müssen jedoch nicht identisch sein.

Automatisch geprüft werden sollten außerdem:

  • unzulässige Dateien,
  • Source Maps,
  • Secrets,
  • ungenutzte Berechtigungen,
  • fehlende Lokalisierungen,
  • falsche Icon-Pfade,
  • Versionsabweichungen zwischen Manifesten.

Automatisierung entfernt die Store-Prüfung nicht. Sie entfernt Fehler, die einen Prüfer niemals erreichen sollten.

Welcher Browser war am einfachsten?

Die Antwort hängt davon ab, was gemessen wird.

Einfachster Start: Chrome

Die meiste Dokumentation, die meisten Beispiele und Werkzeuge. Eine gute Wahl für die grundlegende MV3-Version.

Einfachste Code-Portierung: Edge

Wenn die Chrome-Version korrekt ist, sind die technischen Unterschiede häufig klein. Die separate Veröffentlichungsarbeit bleibt.

Bester Unabhängigkeitstest: Firefox

Nicht immer am einfachsten, aber sehr wertvoll. Er deckt versehentlich an Chromium gebundenen Code auf und erzwingt Ordnung beim Build.

Höchster Gesamtaufwand: Safari

Nicht nur wegen der API. Xcode, App, Signierung, App Store und Tests auf Apple-Geräten kommen hinzu. Die Probleme bei Loudly, TabZoo und LoopIt zeigten außerdem, dass eine funktionierende Oberfläche noch keine funktionierende Funktion bedeutet.

Was würden wir heute anders machen?

1. Safari wäre ab dem ersten Sprint Teil des Plans

Safari müsste nicht sofort den vollständigen Funktionsumfang besitzen. Es sollte jedoch ein funktionsfähiges Xcode-Grundprojekt und regelmäßige Tests des Basisablaufs geben.

2. Firefox würde früher Teil der CI

Nicht nur der Build, sondern auch Tests in einem echten Firefox.

3. Jede Funktion hätte einen eindeutigen Besitzer des Zustands

Vor der Implementierung würden wir festlegen, ob der Zustand zum Content Script, Background, Pop-up oder Storage gehört. Viele Kommunikationsfehler entstehen aus einer unklaren Antwort auf diese Frage.

4. Berechtigungen würden gemeinsam mit der Funktion entworfen

Jede neue Berechtigung sollte besitzen:

  • technische Begründung,
  • Text für den Store,
  • Szenario bei Ablehnung,
  • Test des Verhaltens ohne Zustimmung.

5. Das Listing läge im Repository

Beschreibung, Kurztext, Release Notes, Suchbegriffe, Datenschutzrichtlinie und Grafiken sollten eine Änderungshistorie haben.

6. Wir würden Daten ab der ersten Veröffentlichung messen

Die nächste Stufe des Berichts sollte enthalten:

  • Zeit vom Einreichen bis zur Veröffentlichung,
  • Anzahl der Ablehnungen,
  • Grund jeder Ablehnung,
  • Anzahl plattformspezifischer Änderungen,
  • Anzahl der erst außerhalb von Chrome gefundenen Regressionen,
  • Zeit für die Vorbereitung eines Updates,
  • Größe des gemeinsamen und plattformspezifischen Codes.

Wir rekonstruieren diese Werte heute nicht aus dem Gedächtnis, weil wir Erfahrung von Statistik trennen möchten. Künftig ermöglichen sie noch präzisere Berichte.

Empfohlene Architektur einer plattformübergreifenden Erweiterung

src/
  core/
    domain/
    storage/
    validation/
  platform/
    api.ts
    capabilities.ts
    messaging.ts
  background/
  content/
  popup/
  options/
  locales/

manifests/
  chrome.json
  edge.json
  firefox.json
  safari.json

store/
  chrome/
  edge/
  firefox/
  safari/

tests/
  unit/
  integration/
  e2e/
  manual/

Entscheidend ist die Aufteilung der Verantwortlichkeiten:

  • core kennt keinen konkreten Browser;
  • platform übersetzt WebExtensions in eine gemeinsame Schnittstelle;
  • UI-Flächen werden soweit sinnvoll geteilt;
  • Manifeste und Store-Assets sind ausdrücklich plattformspezifisch;
  • manuelle Tests besitzen dokumentierte Szenarien und existieren nicht nur im Gedächtnis des Autors.

Fazit

Die wichtigste Erkenntnis aus neun Erweiterungen ist einfach:

WebExtensions ermöglicht die Pflege eines gemeinsamen Produkts, entbindet aber nicht davon, vier korrekte Releases zu erstellen.

Chrome bietet den besten Startpunkt. Edge ist meist die einfachste technische Portierung. Firefox ist der wertvollste Test echter Kompatibilität. Safari verlangt, die Erweiterung als Teil einer Apple-App zu behandeln und nicht als weitere ZIP-Variante.

Die größten Probleme entstanden nicht dort, wo für eine einzelne API-Methode kein Gegenstück existierte. Sie entstanden an der Schnittstelle von:

  • Prozesslebenszyklus,
  • Zustand,
  • Webseite,
  • Oberfläche,
  • Berechtigungen,
  • Paketierung,
  • Store-Prüfung.

Ein effektives Team beginnt daher nicht mit der Frage: „Wie kopieren wir die Chrome-Erweiterung in drei weitere Stores?“ Es beginnt mit:

  • Was ist der gemeinsame Produktkern?
  • Welche Fähigkeiten sind plattformspezifisch?
  • Wo wird Zustand gespeichert?
  • Wie bestätigen wir den tatsächlichen Effekt einer Funktion?
  • Wie begrenzen wir Berechtigungen?
  • Wie reproduzieren wir jeden Build?
  • Wie testen wir ein Update und nicht nur eine saubere Installation?

Nach diesen Erfahrungen halten wir eine gemeinsame Codebasis weiterhin für die richtige Strategie. Wir tun jedoch nicht so, als wären vier Browser eine einzige Umgebung.

Gerade die Akzeptanz der Unterschiede ermöglicht es, Code zu teilen, ohne Qualität zu verlieren.

Quellen

  1. POLPROG, Startseite und Informationen zum Erweiterungsportfolio
  2. POLPROG, Herausgeberprofil bei Firefox Add-ons
  3. Apple Developer, Safari Extensions
  4. Apple Developer, Meet Safari Web Extensions
  5. Chrome for Developers, Migrate to a service worker
  6. Chrome for Developers, Extension service worker lifecycle
  7. MDN, Chrome incompatibilities
  8. MDN, Differences between API implementations
  9. MDN, browser_specific_settings
  10. Chrome for Developers, Events in extension service workers
  11. Chrome for Developers, Testing MV3 service worker suspension
  12. Chrome for Developers, Chrome Web Store privacy fields and permissions
  13. Microsoft Learn, Port a Chrome extension to Microsoft Edge
  14. Microsoft Learn, Publish a Microsoft Edge extension
  15. MDN, Build a cross-browser extension
  16. Mozilla Extension Workshop, Submitting an add-on
  17. Mozilla Extension Workshop, Signing and distribution overview
  18. Mozilla Extension Workshop, Add-on Policies
  19. Apple Developer, App Review Guidelines, Safari extensions
  20. Mozilla, Approach to Manifest V3
  21. Pantelaios und Kapravelos, Manifest V3 Unveiled
  22. Polčák et al., Developers Insight on Manifest V3

Die wichtigste Erkenntnis aus neun Erweiterungen ist einfach: WebExtensions ermöglicht die Pflege eines gemeinsamen Produkts, entbindet aber nicht davon, vier korrekte Releases zu erstellen. Chrome bietet den besten Startpunkt. Edge ist meist die einfachste technische Portierung. Firefox ist der wertvollste Test echter Kompatibilität. Safari verlangt, die Erweiterung als Teil einer Apple-App zu behandeln und nicht als weitere ZIP-Variante.

Browser Extensions Dev Tools Chrome Firefox Safari Comparison

Häufig gestellte Fragen

Kann eine Erweiterung in Chrome, Firefox, Edge und Safari funktionieren?

Ja. WebExtensions bietet eine große gemeinsame API-Fläche. Plattformtests, Manifestvarianten, getrennte Paketierung und angepasste Veröffentlichungsprozesse bleiben dennoch notwendig.

Funktioniert eine Chrome-Erweiterung ohne Änderungen in Edge?

Oft funktioniert sie nach kleinen Anpassungen, weil Edge Chromium verwendet. Trotzdem sind ein eigener Eintrag im Microsoft Partner Center, Datenschutzerklärungen, Metadaten und Zertifizierung erforderlich.

Unterstützt Firefox Manifest V3?

Ja. Firefox unterstützt Manifest V3, behält jedoch eigene Lösungen und Unterschiede. Neue MV3-Erweiterungen benötigen eine ID in browser_specific_settings, und neue AMO-Einreichungen müssen Berechtigungen zur Datenerfassung deklarieren.

Braucht man separaten Code für Firefox?

Nicht die gesamte Codebasis. Am besten wird der Kern geteilt und die Unterschiede werden in einem API-Adapter und der Manifest-Konfiguration isoliert.

Warum verliert der Service Worker einer Erweiterung seinen Zustand?

Chrome kann einen inaktiven Extension Service Worker beenden. Später benötigte Daten sollten nicht ausschließlich in Prozessvariablen im Arbeitsspeicher liegen.

Konvertiert Safari eine Chrome-Erweiterung automatisch?

Apple stellt einen Konverter bereit, der ein Safari-Web-Extension-Projekt erstellt, garantiert aber kein identisches Verhalten. Funktionen müssen weiterhin getestet, Xcode konfiguriert, die App signiert und der App-Store-Prozess durchlaufen werden.

Welcher Browser ist für Erweiterungsentwickler am schwierigsten?

Nach unserer Erfahrung verursacht Safari den höchsten Gesamtaufwand aufgrund von Runtime, Xcode, Signierung, Container-App und App-Store-Prüfung.

Ist eine Datenschutzrichtlinie nötig, wenn die Erweiterung nichts versendet?

Oft ist sie dennoch sinnvoll, und die Anforderungen hängen von Store und Berechtigungen ab. Es sollte klar beschrieben werden, welche Daten gelesen werden, wo sie gespeichert werden und ob sie das Gerät verlassen.

Wie testet man Multimedia-Erweiterungen?

Das Öffnen des Pop-ups reicht nicht. Der tatsächliche Effekt muss geprüft werden: Audioänderung, Loop-Bereich, Player-Verhalten, SPA-Navigation, Tab-Wechsel und Wiederherstellung des Zustands nach einem Neustart.

Lohnt sich die Veröffentlichung in vier Stores?

Ja, wenn die Zielgruppe diese Browser tatsächlich nutzt und das Team einen separaten Veröffentlichungsprozess pflegen kann. Zertifizierung, Metadaten, Tests und spätere Updates müssen berücksichtigt werden, nicht nur die erste Portierung.

War das hilfreich?

Neue Artikel per E-Mail erhalten

Eine kurze E-Mail pro neuem Wissens-Artikel. Kein Spam, Abmeldung mit einem Klick.

Wir nutzen Ihre E-Mail nur, um neue Artikel zu versenden. Keine Weitergabe an Dritte.

Zurück zu Wissen