Chrome vs Firefox vs Edge vs Safari: rapport over 9 extensies Skip to content

Blog

Praktische kennis over frontend, AI-tools en softwareontwikkeling.

Chrome vs Firefox vs Edge vs Safari: wat we leerden van het uitbrengen van 9 browserextensies

Gepubliceerd: 17 min lezen POLPROG Browser Extensions

Negen extensies, vier browsers en veel meer dan één bestand `manifest.json`. We laten zien waar gedeelde code werkelijk ophoudt, waarom Safari een apart proces vereist en welke fouten pas door Firefox en de extensiewinkels zichtbaar worden.

Op papier zou een moderne browserextensie bijna vanzelf een multiplatformproduct moeten zijn. Chrome, Firefox, Edge en Safari ondersteunen WebExtensions, gebruiken een vergelijkbaar bestand manifest.json en bieden soortgelijke mechanismen: content scripts, opslag, communicatie tussen contexten, een knop in de werkbalk en instellingenpagina's.

Dat klopt, maar slechts tot op zekere hoogte.

Na het publiceren en porteren van negen POLPROG-extensies weten we dat gedeelde code niet hetzelfde is als één gedeeld product. Het grootste deel van de bedrijfslogica kan worden hergebruikt, maar browsergedrag, de levenscyclus van het achtergrondproces, de interface, machtigingen, verpakking en beoordeling door de winkel blijven afzonderlijke problemen.

Het portfolio bestaat uit:

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

Dit zijn geen negen kopieën van hetzelfde type add-on. De verzameling bevat hulpmiddelen voor video, audioversterking, privacy, gegevensopschoning, ontwikkeling, tabbladbeheer en een lichtgewicht spel. De problemen beperkten zich daarom niet tot één API. Ze hadden betrekking op service workers, pop-ups, content scripts, audio, opslag, pictogrammen, machtigingen en het publicatieproces.

POLPROG onderhoudt publiekelijk negen extensieproducten, die aanvankelijk vooral voor Chrome en Firefox zijn uitgebracht en later ook naar Edge en Safari zijn geporteerd. [1][2]

Dit artikel is geen laboratoriumbenchmark. We hebben vanaf de eerste commit niet iedere minuut per winkel gemeten. Daarom zullen we niet beweren dat Safari exact 2,7 keer zoveel kost als Chrome of dat 94% van de code wordt gedeeld. Dat zou schijnnauwkeurigheid zijn.

We kunnen wel iets nuttigers laten zien: welke aannames onjuist bleken, waar echte storingen optraden en hoe we het volledige proces vandaag vanaf nul zouden ontwerpen.

Bronnen voor het laatst gecontroleerd: 17 juli 2026.

Vier browsers, vier verschillende rollen

PlatformRol in ons procesGrootste voordeelMeest voorkomende valkuil
ChromeBelangrijkste basis voor Manifest V3-compatibiliteitBreedste documentatie en grootste extensiemarktOnderbroken service worker en strenge machtigingseisen
EdgeChromium-gebaseerde portKleine codeverschillen ten opzichte van ChromeAfzonderlijk Partner Center, metadata en certificering
FirefoxOnafhankelijke WebExtensions-implementatieLegt Chromium-afhankelijke aannames goed blootVerschillen in API en manifest, ondertekening en broncodevereisten
SafariAfzonderlijk product binnen het Apple-ecosysteemToegang tot gebruikers van macOS, iOS en iPadOSXcode, container-app, ondertekening en ander runtimegedrag

MDN benadrukt dat WebExtensions add-ons na minimale wijzigingen in de belangrijkste browsers moet laten werken, maar documenteert tegelijk belangrijke verschillen tussen Chrome, Firefox en Safari in API-beschikbaarheid, manifests en asynchrone bewerkingen. [7][8]

Dat sluit goed aan op onze ervaring. “Minimale wijzigingen” zijn realistisch voor een eenvoudige add-on. Hoe meer een extensie ingrijpt in de pagina, media, de levenscyclus van tabbladen of het achtergrondproces, hoe minder bruikbaar het woord “minimaal” wordt.

Les 1: één codebase, ja; één manifest, niet noodzakelijk

Het beste uitgangspunt is gedeelde logica met afzonderlijke buildconfiguraties.

In de praktijk werkte een structuur het prettigst waarin het volgende wordt gedeeld:

  • functielogica,
  • gegevensmodellen,
  • opslagmodules,
  • validatie,
  • het grootste deel van de pop-up- en instellingeninterface,
  • lokalisaties,
  • unit tests.

Afzonderlijk blijven:

  • manifestvarianten,
  • add-on-identifiers,
  • minimale browserversies,
  • achtergrondconfiguratie,
  • een deel van de machtigingen,
  • pictogrammen en winkelassets,
  • verpakking,
  • ondertekening,
  • publicatiescripts.

Het gaat niet om vier handmatig gekopieerde mappen. Dat leidt snel tot verschillen. Een beter model gebruikt gedeelde bronnen plus een generator of configuratielaag die voor elk platform een apart artefact maakt.

Firefox vereist bijvoorbeeld eigen instellingen in browser_specific_settings. In Manifest V3 is een extensie-ID nodig voor ondertekening en sinds november 2025 moeten nieuwe add-ons die naar AMO worden gestuurd ook instellingen voor gegevensverzameling declareren. [9]

Safari vereist daarentegen een Xcode-project en een applicatie die de extensie bevat. Apple levert een WebExtension-converter, maar het resultaat moet nog steeds worden behandeld als een native project dat wordt ondertekend en via de App Store wordt verspreid. [3][4]

Een gedeeld manifest zou dus een kunstmatige besparing zijn. Enkele kleine, expliciete verschillen zijn eenvoudiger te onderhouden dan één bestand vol uitzonderingen en voorwaarden.

Les 2: Manifest V3 heeft het browsergedrag niet gelijkgetrokken

Manifest V3 verbeterde een deel van de compatibiliteit en structureerde het extensiemodel, maar creëerde geen identieke runtime.

De opvallendste verandering in Chrome is de vervanging van permanente achtergrondpagina's door een extension service worker. Google beschrijft deze als een centrale eventhandler die wordt gestart wanneer dat nodig is. Het proces kan worden beëindigd, en variabelen die alleen in het geheugen staan verdwijnen ermee. [5][6]

Dat heeft directe gevolgen.

Code zoals:

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

kan niet de enige bron van waarheid zijn wanneer deze gegevens na een herstart van de service worker opnieuw nodig zijn.

Status moet in drie groepen worden verdeeld:

  1. tijdelijke status die veilig mag verdwijnen;
  2. status die kan worden gereconstrueerd uit actieve tabbladen of de DOM;
  3. permanente status die in storage.local, storage.session of een andere geschikte locatie moet worden opgeslagen.

Ook de registratie van listeners is belangrijk. Chrome adviseert eventhandlers in de globale scope van het script te declareren, zodat ze synchroon worden geregistreerd wanneer de service worker ontwaakt. Een listener die pas na asynchrone initialisatie wordt aangemaakt, kan juist het event missen dat de worker heeft gewekt. [10]

Tijdens ontwikkeling is dit makkelijk te missen. Geopende DevTools kunnen de levenscyclus van de service worker beïnvloeden, terwijl de fout pas tijdens normaal gebruik optreedt. Google beschreef vergelijkbare problemen bij MV3-migraties: het onderbreken van het proces kan timers stoppen en status uit het geheugen verwijderen. [11]

De belangrijkste regel luidt daarom:

Het achtergrondproces van een extensie moet worden ontworpen als een onderbreekbare eventhandler, niet als een kleine Node.js-server die voortdurend draait.

Les 3: Chrome is een goed startpunt, maar een slechte enige testomgeving

Chrome is de natuurlijke basis voor een Manifest V3-project. Het heeft uitgebreide documentatie, voorbeelden, ontwikkelaarstools en het grootste add-on-ecosysteem.

Tegelijk geeft alleen in Chrome testen een vals gevoel van compatibiliteit.

Als code in Chrome en Edge werkt, bevestigt dat vooral compatibiliteit met Chromium. Het bevestigt niet:

  • correct gedrag in Gecko,
  • correct gedrag in WebKit,
  • bestendigheid tegen een andere pop-up-levenscyclus,
  • werking met een ander machtigingsmodel,
  • correcte schaling van pictogrammen,
  • correct audiogedrag,
  • identieke API-semantiek.

De Chrome Web Store vereist dat een extensie één beperkt en gemakkelijk te begrijpen doel heeft. Ook is het minimale aantal machtigingen vereist, met een rechtvaardiging voor elke machtiging en consistente verklaringen over gegevensgebruik. Te brede machtigingen kunnen tot afwijzing leiden. Manifest V3 verbiedt bovendien het laden en uitvoeren van extern gehoste code. [12]

Deze eisen beïnvloeden de architectuur eerder dan verwacht. “Voor de zekerheid” toegang tot alle websites toevoegen is niet neutraal. Later moet dit worden uitgelegd aan de reviewer en de gebruiker. Een betere oplossing kan activeTab, optionele host permissions of toegang tot specifieke domeinen zijn.

Chrome leerde ons dus twee tegengestelde dingen:

  • het is een goede plek om de basisvariant van MV3 vast te leggen;
  • het mag niet alle aannames in de gedeelde laag bepalen.

Les 4: Edge is technisch de eenvoudigste port, maar geen gratis distributiekanaal

Microsoft beschrijft het porteren van een bestaande Chrome-extensie naar Edge officieel als een afzonderlijk ondersteund scenario. Omdat beide browsers Chromium gebruiken, zijn verschillen in de kerncode vaak klein. [13]

In onze projecten vereiste Edge meestal de minste technische wijzigingen. Dat betekende echter geen publicatie “met één klik”.

De extensie wordt naar een apart Partner Center gestuurd, waar men:

  • een eigen ZIP-pakket uploadt,
  • beschikbaarheid en markten instelt,
  • een categorie kiest,
  • het enkele doel beschrijft,
  • iedere machtiging motiveert,
  • het gebruik van externe code verklaart,
  • gegevenspraktijken beschrijft,
  • vermeldingen voor verschillende talen voorbereidt,
  • afzonderlijke afbeeldingen en screenshots uploadt,
  • opmerkingen voor het certificeringsteam toevoegt. [14]

Net als Google vereist Microsoft een duidelijk doel en de kleinst mogelijke set machtigingen. Partner Center waarschuwt dat onvolledige of tegenstrijdige verklaringen de certificering kunnen vertragen of tot afwijzing kunnen leiden. [14]

Edge is daarmee een goed voorbeeld van het verschil tussen portkosten en kanaalkosten.

De code kan bijna identiek zijn, maar het team moet nog steeds onderhouden:

  • een afzonderlijk productrecord,
  • een afzonderlijke reviewstatus,
  • afzonderlijke metadata,
  • afzonderlijke grafische varianten,
  • een apart updateproces,
  • consistente privacyverklaringen.

Voor één extensie is deze overhead beperkt. Voor negen producten wordt het een terugkerend operationeel proces.

Les 5: Firefox ontdekt het beste code die “per ongeluk alleen voor Chrome” is geschreven

Firefox gebruikt WebExtensions, maar is geen Chromium. Juist daarom is het zo'n waardevolle testomgeving.

Het bekendste verschil betreft namespace en asynchrone code. Chrome gebruikte historisch chrome en callbacks, terwijl Firefox en Safari browser en promises gebruiken. In Manifest V3 voegden Chrome en Edge bij veel methoden promise-ondersteuning toe, maar niet alle verschillen verdwenen. Mozilla adviseert code met browser en promises te schrijven en indien nodig WebExtension browser API Polyfill te gebruiken. [8][15]

Het is niet verstandig door het hele project voorwaarden te verspreiden zoals:

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

rond iedere API-call. Beter is een kleine adapterlaag:

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

en de verschillen op één plaats oplossen.

Firefox dwingt ook meer discipline af bij publicatie. Extensies moeten worden ondertekend, zelfs als ze in de standaardconfiguratie zelfstandig worden verspreid. AMO valideert het pakket, en geminificeerde of moeilijk leesbare code kan vereisen dat het volledige bronpakket wordt meegestuurd. Mozilla kan na publicatie ook een handmatige review uitvoeren en de huidige of een eerdere versie afwijzen. [16][17][18]

Vanuit kwaliteitsperspectief is dat een voordeel. Het proces dwingt af dat de build:

  • reproduceerbaar,
  • gedocumenteerd,
  • vrij van onnodige obfuscatie,
  • in overeenstemming met het beschreven gedrag,
  • controleerbaar zonder interne kennis van de auteur is.

Firefox legde ook problemen bloot waar Chromium toleranter was. Deze betroffen berichtenafhandeling, wachten op een promiseantwoord, verschillen in pop-ups en aannames over de aanwezigheid van bepaalde API-eigenschappen.

De belangrijkste les:

Firefox is geen extra selectievakje na afronding van het project. Het is een tweede onafhankelijke runtime die vroeg in het testproces hoort.

Les 6: Safari is geen winkelport, maar een afzonderlijke productfase

Apple ondersteunt WebExtensions en levert een hulpmiddel om extensies uit Chrome, Firefox of Edge te converteren. Toch is het Safari-proces fundamenteel anders. [3][4]

De extensie wordt onderdeel van een applicatie die in Xcode wordt gebouwd. Het team beheert:

  • het applicatieproject,
  • het extensietarget,
  • de bundle identifier van de app,
  • een afzonderlijke bundle identifier van de extensie,
  • ondertekening,
  • profielen en certificaten,
  • het applicatiepictogram,
  • entitlements,
  • archivering,
  • App Store Connect,
  • beoordeling in de App Store.

Apple vereist dat de extensie werkt met de huidige Safari-versie voor het betreffende systeem, niet ingrijpt in de Safari-interface en niet om toegang tot meer websites vraagt dan nodig is. [19]

Hier verschenen de meest concrete problemen in ons portfolio.

Loudly: de interface werkte, maar het geluid werd niet versterkt

Loudly grijpt in op audio die op een pagina wordt afgespeeld. In de Safari-versie kon de interface worden weergegeven, konden instellingen worden aangepast en leek het product te werken. Het werkelijke audiosignaal werd echter niet versterkt.

Dit type fout is erger dan een duidelijke crash. De smoke test “de pop-up opent” slaagt, maar de belangrijkste productbelofte wordt niet nagekomen.

Conclusie: bij multimedia-extensies moet een functionele test het eindresultaat meten, niet alleen de toestand van de interface.

TabZoo: een wit scherm in plaats van de applicatie

De Safari-versie van TabZoo kon een lege witte pagina tonen. Zo'n probleem kan worden veroorzaakt door een initialisatiefout, assetpaden, een onjuiste context of een uitzondering vóór het renderen.

In Chromium kan een vergelijkbare fout verborgen blijven wanneer de startvolgorde of API-beschikbaarheid anders is.

Conclusie: iedere extensieweergave moet een minimaal diagnostisch mechanisme en afhandeling van initialisatiefouten hebben. Een lege pagina mag niet de eindtoestand van het product zijn.

LoopIt: één klik opende twee interfaces

In LoopIt zorgde een klik op het pictogram in Safari voor het verschijnen van een pop-up en een extra extensiepaneel. Dit was een conflict tussen een declaratief ingesteld pop-upvenster en handmatige klikafhandeling.

In één browser leek het gedrag correct, in een andere leidde het tot een dubbele reactie.

Conclusie: het moet duidelijk zijn wie eigenaar is van de klik op de werkbalkknop. Of de knop heeft default_popup, of het event wordt programmatisch afgehandeld. Beide mechanismen combineren vereist zeer bewust ontwerp.

Deze drie gevallen laten zien waarom het uitvoeren van Apples converter de port niet voltooit. De converter brengt de structuur over. Hij bevestigt niet dat het gedrag semantisch gelijk is.

Les 7: video- en audio-extensies zijn moeilijker dan de pop-up doet vermoeden

Vier van onze producten zijn sterk afhankelijk van media:

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

Elk product moet verschillende werelden coördineren:

  • de DOM van de pagina,
  • het audio- of video-element,
  • het content script,
  • de pop-up,
  • het achtergrondproces,
  • opgeslagen instellingen,
  • SPA-navigatie,
  • wisselingen van het actieve tabblad.

De meeste fouten ontstaan niet binnen één functie, maar op de grens tussen deze contexten.

Een voorbeeld:

  1. de gebruiker opent de pop-up;
  2. de pop-up vraagt het content script om de huidige status;
  3. de pagina heeft zojuist zonder volledige reload een andere video geopend;
  4. het oude video-element is verwijderd;
  5. het content script bewaart nog een verwijzing naar het vorige element;
  6. de pop-up toont een correcte waarde, maar wijzigt een inactieve speler.

Nog een setTimeout toevoegen is geen oplossing. Er is een expliciet statusmodel nodig:

  • het actieve element identificeren,
  • DOM-wijzigingen observeren,
  • handlers opnieuw koppelen,
  • uitvoering van opdrachten bevestigen,
  • de interface pas na een antwoord synchroniseren,
  • status herstellen na herstart van het achtergrondproces.

Bij diensten zoals YouTube moet ook SPA-navigatie worden meegenomen. Een andere video openen veroorzaakt niet altijd een volledige documentreload, zodat een eenmalige initialisatie van het content script niet voldoende is.

Les 8: pictogram en pop-up zijn onderdeel van de implementatie, niet alleen branding

Een multiplatformbuild kan technisch correct zijn en er toch verkeerd uitzien.

Tijdens onze tests waren pictogrammen:

  • te groot voor het beschikbare vlak,
  • zonder veilige marge,
  • tegen de randen geplaatst,
  • optisch kleiner dan andere extensiepictogrammen ondanks dezelfde bestandsafmetingen,
  • correct in de winkel maar onduidelijk in de browserwerkbalk.

De PNG-afmetingen lossen het probleem niet op. Het gaat om de visuele grootte van het symbool binnen het canvas.

Hetzelfde geldt voor pop-ups. Dezelfde CSS-breedte kan anders worden weergegeven door:

  • fontrendering,
  • standaardstijlen van formulierbesturingen,
  • scrollbar-gedrag,
  • hoogteberekening,
  • systeemmarges,
  • beeldschaling,
  • lichte en donkere modus.

Daarom bereiden we assets tegenwoordig als set voor, niet als één afbeelding:

  • bron-SVG,
  • rastervarianten die het manifest vereist,
  • gecontroleerde safe area,
  • Safari-appicoon,
  • afbeeldingen voor de winkelvermelding,
  • winkelscreenshots.

De extensie-interface moet ook minimale en maximale afmetingen hebben en leesbaar blijven wanneer vertalingen langer worden.

Les 9: publicatie is een afzonderlijk operationeel product

De grootste organisatorische fout is aannemen dat het werk eindigt na het genereren van de ZIP.

Elke winkel heeft een eigen vertrouwensmodel.

Chrome Web Store

Chrome vereist een duidelijk enkel doel, minimale machtigingen, gegevensverklaringen en een privacybeleid. Op afstand uitgevoerde code is in Manifest V3 verboden. [12]

De productbeschrijving moet overeenkomen met het echte gedrag. Als de vermelding een functie belooft die de reviewer niet kan uitvoeren, is dat geen marketingprobleem maar een certificeringsprobleem.

Firefox Add-ons

AMO valideert het pakket automatisch, kan bronnen eisen voor gebouwde code en behoudt de mogelijkheid van latere handmatige beoordeling. Beveiligings- en privacywaarschuwingen moeten worden opgelost, ook wanneer technisch doorgaan mogelijk is. [16][17]

Microsoft Edge Add-ons

Partner Center vereist afzonderlijke informatie voor beschikbaarheid, privacy en taalvermeldingen. Elke machtiging moet worden gemotiveerd en de informatie moet overeenkomen met manifest en extensiegedrag. [14]

Safari en de App Store

Safari voegt een applicatielaag, ondertekening, App Store-metadata en de richtlijnen voor Apple-apps toe. De extensie moet werken met de huidige Safari-versie en toegang tot websites beperken tot het noodzakelijke minimum. [19]

Negen extensies betekenen daardoor niet negen vermeldingen. Bij volledige ondersteuning van vier platforms ontstaan maximaal 36 product-browsercombinaties, zonder taalversies en afzonderlijke varianten voor Apple-apparaten mee te tellen.

Dat is voldoende reden om metadata in het repository op te slaan.

Les 10: er is een testmatrix nodig, geen notitie “extensie controleren”

Voor iedere extensie onderhouden we dezelfde testbasis en voegen daarna functiespecifieke gevallen toe.

Minimale smoke test

Na iedere build controleren we:

  1. schone installatie;
  2. update vanaf de vorige versie;
  3. verschijnen van het pictogram;
  4. openen van de pop-up;
  5. geen initialisatiefouten;
  6. opslaan en opnieuw lezen van instellingen;
  7. werking na sluiten en opnieuw starten van de browser;
  8. werking nadat de achtergrond is onderbroken;
  9. gedrag zonder toestemming voor de pagina;
  10. gedrag op een niet-ondersteunde pagina.

Communicatietest

Afzonderlijk testen we:

  • pop-up → background,
  • pop-up → content script,
  • content script → background,
  • asynchroon antwoord,
  • geen actief tabblad,
  • tabbladreload,
  • SPA-navigatie,
  • opnieuw injecteren van het content script,
  • sluiten van de pop-up voordat het antwoord binnenkomt.

Functiespecifieke test

Bij Loudly is de schuifregelaar verplaatsen niet genoeg. De verandering van het audioniveau moet worden bevestigd.

Bij LoopIt moet worden gecontroleerd of het afspelen werkelijk terugkeert naar het gekozen bereik.

Bij AutoScroll moeten verschillende layouts, volledig scherm, videowisseling en handmatig scrollen worden getest.

Bij ClickClean moet het effect op echte testgegevens worden gecontroleerd, niet alleen de melding “gereed”.

Bij DevScope en LeakLens moet het rapport worden gevalideerd op sites met verschillende CSP-regels, aantallen frames en headersets.

Platformspecificieke test

Tot slot komen browserspecifieke gevallen:

  • herstart van de service worker in Chromium,
  • ondertekend Firefox-pakket,
  • host permissions in Firefox,
  • installatie en activering van de extensie in Safari,
  • macOS- en iOS-versies indien ondersteund,
  • update via de winkel in plaats van alleen lokale sideloading.

Les 11: geautomatiseerde tests vervangen geen echte browser-QA

Automatisering is noodzakelijk, maar heeft grenzen.

Unit tests zijn goed voor:

  • bedrijfslogica,
  • validatie,
  • opslagmigraties,
  • gegevensformattering,
  • regels voor functieactivering.

Integratietests kunnen controleren:

  • het manifest,
  • aanwezigheid van bestanden,
  • communicatie tussen modules,
  • basis-API-calls,
  • volledigheid van lokalisaties.

E2E-tests in Chromium vinden een groot deel van de regressies in interface en content scripts.

Ze bevestigen niet dat:

  • Firefox alle machtigingen identiek interpreteert,
  • Safari audio correct aanpast,
  • de App Store het juiste target start,
  • de pop-up niet tweemaal wordt geopend,
  • het pictogram correct oogt in de systeembalk.

De duurste fouten in onze ports waren niet eenvoudig te vinden met unit tests. Het waren integratiefouten tussen extensie, browser, website en besturingssysteem.

Les 12: de compatibiliteitslaag moet mogelijkheden beschrijven, geen browsernamen

Aan het begin van een project is een voorwaarde zoals deze verleidelijk:

if (browserName === "safari") {
  // speciaal gedrag
}

Soms is dit onvermijdelijk, maar het mag niet het belangrijkste architectuurmodel worden.

Betere vragen zijn:

  • ondersteunt de omgeving deze API?
  • is de pop-up declaratief?
  • is de achtergrond een service worker?
  • is een specifieke methode beschikbaar?
  • vereist de functie een native container?
  • stelt de pagina het benodigde media-element beschikbaar?

Code op basis van mogelijkheden is beter bestand tegen versieverschillen en eenvoudiger te testen.

Een platformlaag kan bijvoorbeeld aanbieden:

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",
};

Dit verwijdert verschillen niet. Het maakt ze expliciet en concentreert ze op één plaats.

Les 13: privacy-first vereenvoudigt publicatie werkelijk

POLPROG-extensies worden zonder analytics, tracking en externe backend ontworpen wanneer die niet nodig zijn.

Dat is niet alleen een merkbeslissing. Het vereenvoudigt:

  • beschrijving van gegevensstromen,
  • privacybeleid,
  • rechtvaardiging van machtigingen,
  • code review,
  • risico op een gegevenslek,
  • overeenstemming tussen vermelding en code.

Dit betekent niet dat een privacyvriendelijke extensie geen documentatie nodig heeft. Als een add-on pagina-inhoud, geschiedenis, tabbladen of cookies leest, moet duidelijk worden uitgelegd waarom, ook wanneer niets naar een server wordt verzonden.

Chrome en Edge vereisen motivatie voor machtigingen en verklaringen over gegevensgebruik. Firefox vereist dat nieuwe add-ons informatie geven over machtigingen die met gegevensverzameling samenhangen. Safari adviseert websitetoegang tot het noodzakelijke minimum te beperken. [9][12][14][19]

Vanaf de eerste dag ontwerpen met minimale machtigingen is veel eenvoudiger dan overbodige rechten na een afwijzing verwijderen.

Les 14: de releasepipeline moet producten bouwen, geen archief final-final.zip

Bij negen extensies is handmatige verpakking al snel niet meer veilig.

Een goede pipeline moet:

  1. de versie controleren;
  2. het basism anifest valideren;
  3. het platformmanifest genereren;
  4. de code bouwen;
  5. de juiste pictogrammen kopiëren;
  6. op externe code controleren;
  7. tests uitvoeren;
  8. afzonderlijke artefacten genereren;
  9. checksums maken;
  10. changelog en winkelinformatie voorbereiden.

Voorbeeldoutput:

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

De versie moet uit één bron van waarheid komen, maar de artefacten hoeven niet identiek te zijn.

Daarnaast is het nuttig automatisch te controleren op:

  • verboden bestanden,
  • sourcemaps,
  • geheimen,
  • ongebruikte machtigingen,
  • ontbrekende lokalisaties,
  • onjuist pictogrampad,
  • versieverschillen tussen manifests.

Automatisering verwijdert winkelreview niet. Ze verwijdert fouten die daar nooit zouden mogen aankomen.

Welke browser bleek het eenvoudigst?

Het antwoord hangt af van wat wordt gemeten.

Eenvoudigste start: Chrome

De meeste documentatie, voorbeelden en tools. Een goede keuze voor de basisversie van MV3.

Eenvoudigste codeport: Edge

Als de Chrome-versie correct is, zijn de technische verschillen meestal klein. Afzonderlijk publicatiewerk blijft bestaan.

Beste onafhankelijkheidstest: Firefox

Niet altijd het eenvoudigst, maar zeer waardevol. Het onthult code die per ongeluk aan Chromium is gekoppeld en dwingt builddiscipline af.

Grootste totale inspanning: Safari

Niet alleen door de API. Xcode, de app, ondertekening, App Store en tests op Apple-apparaten komen erbij. De problemen met Loudly, TabZoo en LoopIt lieten ook zien dat een werkende interface niet hetzelfde is als een werkende functie.

Wat zouden we anders doen als we vandaag begonnen?

1. Safari zou vanaf de eerste sprint in het plan staan

Het hoeft niet onmiddellijk alle functies te bevatten. Er moet wel een werkend Xcode-projectskelet en regelmatige test van de basisflow zijn.

2. Firefox zou eerder deel uitmaken van CI

Niet alleen de build, maar tests uitgevoerd in echte Firefox.

3. Iedere functie zou een eigenaar van status hebben

Vóór implementatie bepalen we of status bij het content script, background, de pop-up of opslag hoort. Veel communicatieproblemen ontstaan door een onduidelijk antwoord.

4. Machtigingen zouden samen met de functie worden ontworpen

Iedere nieuwe machtiging moet hebben:

  • technische motivatie,
  • tekst voor de winkel,
  • scenario bij weigering,
  • test van gedrag zonder toestemming.

5. De winkelvermelding zou in het repository staan

Beschrijving, korte samenvatting, release notes, zoekwoorden, privacybeleid en afbeeldingen moeten een wijzigingsgeschiedenis hebben.

6. We zouden gegevens vanaf de eerste release meten

Een volgende versie van dit rapport moet bevatten:

  • tijd van indiening tot publicatie,
  • aantal afwijzingen,
  • reden van iedere afwijzing,
  • aantal platformspecifieke wijzigingen,
  • aantal regressies dat pas buiten Chrome werd ontdekt,
  • tijd voor voorbereiding van een update,
  • omvang van gedeelde en platformspecifieke code.

We reconstrueren die cijfers vandaag niet uit het geheugen, omdat we ervaring en statistiek gescheiden willen houden. In de toekomst maken ze nauwkeurigere rapporten mogelijk.

Aanbevolen architectuur voor een multiplatformextensie

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/

Het belangrijkste is de verdeling van verantwoordelijkheden:

  • core kent geen specifieke browser;
  • platform vertaalt WebExtensions naar een gedeelde interface;
  • UI-oppervlakken worden waar mogelijk gedeeld;
  • manifests en winkelassets zijn expliciet platformspecifiek;
  • handmatige tests hebben vastgelegde scenario's en bestaan niet alleen in het geheugen van de auteur.

Oordeel

De belangrijkste les uit negen extensies is eenvoudig:

WebExtensions maakt het mogelijk één gedeeld product te onderhouden, maar neemt de noodzaak van vier correcte releases niet weg.

Chrome biedt het beste startpunt. Edge is doorgaans de eenvoudigste technische port. Firefox is de waardevolste test van echte compatibiliteit. Safari vereist dat de extensie als onderdeel van een Apple-app wordt behandeld en niet als nog een ZIP-variant.

De grootste problemen verschenen niet waar een equivalent van één API-methode ontbrak. Ze verschenen op het snijpunt van:

  • levenscyclus van processen,
  • status,
  • de website,
  • de interface,
  • machtigingen,
  • verpakking,
  • winkelreview.

Een effectief team begint daarom niet met de vraag: “Hoe kopiëren we de Chrome-extensie naar drie andere winkels?” Het begint met:

  • wat is de gedeelde productkern?
  • welke mogelijkheden zijn platformspecifiek?
  • waar wordt status opgeslagen?
  • hoe bevestigen we het werkelijke effect van een functie?
  • hoe beperken we machtigingen?
  • hoe reproduceren we iedere build?
  • hoe testen we een update en niet alleen een schone installatie?

Na deze ervaringen beschouwen we één codebase nog steeds als de juiste strategie. We doen alleen niet alsof vier browsers één omgeving zijn.

Juist het accepteren van de verschillen maakt het mogelijk code te delen zonder kwaliteit te verlagen.

Bronnen

  1. POLPROG, homepage en informatie over het extensieportfolio
  2. POLPROG, uitgeversprofiel op 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 en Kapravelos, Manifest V3 Unveiled
  22. Polčák et al., Developers Insight on Manifest V3

De belangrijkste les uit negen extensies is eenvoudig: WebExtensions maakt het mogelijk één gedeeld product te onderhouden, maar neemt de noodzaak van vier correcte releases niet weg. Chrome biedt het beste startpunt. Edge is doorgaans de eenvoudigste technische port. Firefox is de waardevolste test van echte compatibiliteit. Safari vereist dat de extensie als onderdeel van een Apple-app wordt behandeld en niet als nog een ZIP-variant.

Browser Extensions Dev Tools Chrome Firefox Safari Comparison

Veelgestelde vragen

Kan één extensie werken in Chrome, Firefox, Edge en Safari?

Ja. WebExtensions biedt een groot gemeenschappelijk API-oppervlak. Platformspecificieke tests, manifestvarianten, afzonderlijke verpakking en aanpassingen in het publicatieproces blijven nodig.

Werkt een Chrome-extensie zonder wijzigingen in Edge?

Vaak werkt ze na kleine aanpassingen omdat Edge Chromium gebruikt. Er is nog steeds een afzonderlijke vermelding in Microsoft Partner Center, privacyverklaring, metadata en certificering nodig.

Ondersteunt Firefox Manifest V3?

Ja. Firefox ondersteunt Manifest V3, maar behoudt eigen oplossingen en verschillen. Nieuwe MV3-extensies hebben een ID in browser_specific_settings nodig, en nieuwe AMO-inzendingen moeten machtigingen rond gegevensverzameling declareren.

Moet er afzonderlijke code voor Firefox worden onderhouden?

Niet de volledige codebase. Het beste is de kern te delen en verschillen te isoleren in een API-adapter en manifestconfiguratie.

Waarom verliest een extension service worker zijn status?

Chrome kan een inactieve extension service worker beëindigen. Gegevens die later nodig zijn mogen niet uitsluitend in procesvariabelen in het geheugen bestaan.

Converteert Safari een Chrome-extensie automatisch?

Apple levert een converter die een Safari Web Extension-project maakt, maar garandeert geen identiek gedrag. Functies moeten nog steeds worden getest, Xcode moet worden geconfigureerd, de app moet worden ondertekend en het App Store-proces moet worden doorlopen.

Welke browser is het moeilijkst voor extensieontwikkelaars?

Volgens onze ervaring heeft Safari de hoogste totale kosten door runtime, Xcode, ondertekening, container-app en App Store-beoordeling.

Is een privacybeleid nodig als de extensie niets verzendt?

Vaak blijft het nuttig, en vereisten hangen af van winkel en machtigingen. Er moet duidelijk worden uitgelegd welke gegevens de extensie leest, waar ze worden opgeslagen en of ze het apparaat verlaten.

Hoe test je multimedia-extensies?

Alleen de pop-up openen is niet genoeg. Het werkelijke effect moet worden geverifieerd: audioverandering, loopbereik, spelergedrag, SPA-navigatie, wisseling van tabblad en herstel van status na herstart.

Is publiceren in vier winkels de moeite waard?

Ja, wanneer de doelgroep deze browsers werkelijk gebruikt en het team een afzonderlijk releaseproces kan onderhouden. Certificering, metadata, tests en toekomstige updates moeten worden meegerekend, niet alleen de eerste port.

Was dit nuttig?

Ontvang nieuwe artikelen per e-mail

Eén korte e-mail per nieuw blogartikel. Geen spam, uitschrijven in één klik.

We gebruiken je e-mail alleen om nieuwe artikelen te sturen. Geen delen met derden.

Terug naar de blog