Ratgeber · PDF-Historie
Mozilla pdf.js 2011: Wie PDF in den Browser kam
Bis Juni 2011 war PDF im Browser nur über das Adobe-Acrobat-Plugin oder per Download mit externem Reader nutzbar. Mozilla startete pdf.js als Forschungsprojekt, integrierte es in Firefox 19 und machte das Plugin obsolet. Heute ist pdfjs-dist Standard für jedes Browser-PDF-Tool.
Bis Juni 2011 war PDF im Browser ein lästiges Problem. Wer auf einen Link zu einer PDF-Datei klickte, bekam entweder einen Download-Dialog oder, falls Adobes Acrobat-Plugin installiert war, einen oft langsam ladenden Acrobat-Viewer im Browser-Fenster. Beide Lösungen waren unbefriedigend: Downloads brachen den Lesefluss, Plugins waren langsam und sicherheitskritisch. Mozilla änderte das mit pdf.js. Dieser Artikel erzählt, wie ein Forschungsprojekt zur Browser-PDF-Revolution wurde.
Die Situation vor 2011
Anfang 2011 sah die PDF-im-Browser-Welt so aus: Internet Explorer 8 öffnete PDFs entweder mit Acrobat-Plugin (wenn installiert) oder bot Download an. Firefox 4 hatte kein eigenes PDF-Rendering und brauchte ebenfalls das Plugin. Chrome 11 hatte ab Anfang 2011 einen integrierten PDF-Viewer auf Basis von Foxit-Technologie, aber das war proprietär.
Das Adobe-Plugin war das verbreitetste, hatte aber drei große Probleme. Erstens Performance: Plugin-Prozesse kommunizierten via Inter-Process-Communication mit dem Browser, was bei jedem Scroll-Event Latenz erzeugte. Zweitens Stabilität: ein Plugin-Crash konnte den ganzen Browser-Tab mitnehmen, oft sogar das ganze Browser-Fenster. Drittens Sicherheit: 2009 und 2010 gab es dutzende kritische Zero-Day-Vulnerabilities in Acrobat, oft monatelang offen.
Browser-Plugins waren generell die größte Sicherheits-Lücke des Webs. Java-Plugin, Flash-Plugin, Acrobat-Plugin, Silverlight-Plugin: alle hatten regelmäßig kritische Lücken, die für Drive-By-Downloads ausgenutzt wurden. Mozilla wollte diese Angriffsfläche reduzieren.
Andreas Gal und das Mozilla-Research-Team
Andreas Gal war 2011 Forschungsleiter bei Mozilla. Er hatte sich vorher mit JavaScript-Optimierung beschäftigt, unter anderem an der TraceMonkey-JIT-Engine. Im Mai 2011 startete er pdf.js als Mozilla-Forschungsprojekt mit dem ehrgeizigen Ziel, einen kompletten PDF-Renderer in reinem JavaScript zu schreiben.
Am 14. Juni 2011 erscheint auf dem Mozilla-Hacks-Blog der Artikel ‘Why pdf.js’. Gal beschreibt das Ziel: PDF-Rendering ohne Plugin, ohne native Code-Komponente, ohne externe Library, nur mit den Browser-APIs HTML5-Canvas, Web Workers und XHR. Der Code soll als reines JavaScript laufen, was bedeutet: in jedem modernen Browser, nicht nur in Firefox.
Das Team ist klein, aber motiviert. Erste Beta-Builds rendern einfache PDFs in wenigen Sekunden. Komplexe PDFs mit Vektor-Pfaden, eingebetteten Schriften und Transparenz brauchen Wochen Entwicklungsarbeit, weil jedes PDF-Feature einzeln implementiert werden muss. Die PDF 1.7 Spec hat über 800 Seiten und beschreibt hunderte Operatoren, Encodings und Algorithmen.
Die ersten Releases
Im Juli 2011 ist die erste öffentlich nutzbare Version verfügbar. Sie wird als Firefox-Addon ausgeliefert: wer pdf.js installiert, sieht PDFs in einem Browser-Tab statt im Adobe-Plugin. Die Performance ist anfangs nicht überragend, aber stabil. Vor allem öffnet pdf.js PDFs sofort, ohne Plugin-Initialisierung, ohne Inter-Process-Communication.
Über die folgenden 18 Monate verbessert das Team die Performance kontinuierlich. Web Workers werden eingeführt, sodass das Parsing parallel zum UI-Thread läuft. Canvas-Rendering wird optimiert. Schriften-Handling wird robuster, vor allem für asiatische Schriftarten mit CID-Mapping.
Firefox 19: pdf.js wird Default
Am 19. Februar 2013 erscheint Firefox 19. Mit dabei: pdf.js als Default-PDF-Viewer. Das Adobe-Acrobat-Plugin wird nicht mehr automatisch verwendet, auch wenn es installiert ist. Nutzer können in den Einstellungen umschalten, aber Default ist pdf.js.
Das ist ein wichtiger strategischer Schritt von Mozilla. Adobe verliert seinen Status als Default-PDF-Renderer in Firefox. Adobe reagiert nicht öffentlich, aber die Acrobat-Plugin-Entwicklung wird in den folgenden Jahren auslaufen gelassen. 2017 schlägt Adobe sogar selbst vor, Browser-Plugins komplett abzuschaffen und nur noch HTML5 zu nutzen.
Mit Firefox 19 wird pdf.js außerdem aus dem Addon-Status zur Kernkomponente. Updates kommen mit Firefox-Releases statt mit eigenem Update-Zyklus. Mozilla baut Telemetrie ein, um Rendering-Fehler zu erkennen. Der Code zieht von dem ursprünglichen Repository in das offizielle Mozilla-Hauptrepo um.
Die Wende: pdfjs-dist auf npm
Mit Firefox-Integration hört pdf.js nicht auf. Mozilla veröffentlicht den Code separat als pdfjs-dist auf npm. Das ist der Wendepunkt. Plötzlich kann jeder Web-Entwickler einen vollwertigen PDF-Renderer in seine eigene Anwendung einbetten, ohne Lizenz, ohne Adobe, ohne Server.
pdfjs-dist enthält zwei Hauptdateien: das Main-Bundle (pdf.min.mjs) und den Worker (pdf.worker.min.mjs). Der Worker macht das eigentliche PDF-Parsing in einem Hintergrund-Thread, das Main-Bundle stellt nur die API bereit, mit der man Seiten anfordert und auf Canvas rendert. Diese Architektur sorgt dafür, dass auch große PDFs die UI nicht blockieren.
Heute laufen unzählige Browser-PDF-Tools auf pdfjs-dist: PDF-Viewer in Web-Apps, Konvertierer wie unser pdfkonvertieren.de, eingebettete Vorschau-Funktionen in Mail-Clients wie Thunderbird, und sogar einige E-Reader-Anwendungen. Die wöchentlichen npm-Downloads liegen aktuell im siebenstelligen Bereich.
Konkurrenz im Browser: PDFium und Apple Preview
Mit Mozilla pdf.js ist die Browser-PDF-Welt nicht allein. Google hat 2014 mit PDFium einen eigenen PDF-Renderer als Open Source freigegeben, ursprünglich von Foxit entwickelt. PDFium läuft in C++ und ist in Chrome, Edge und Brave als nativer PDF-Viewer integriert. Performance-Vergleich: PDFium ist bei komplexen PDFs schneller als pdf.js, weil C++-Code direkt auf die CPU zugreift, ohne JavaScript-JIT-Overhead.
Apple Preview auf macOS und iOS nutzt eine eigene PDF-Engine als Teil von Core Graphics. Diese ist proprietär, aber sehr performant und auf Apple-Hardware optimiert. Im Safari-Browser kommt diese Engine zum Einsatz, wenn PDFs angezeigt werden.
Für Webentwickler, die einen eigenen PDF-Viewer einbetten wollen, ist pdfjs-dist die einzige praktikable Open-Source-Wahl. PDFium ist als C++-Bibliothek nicht ohne Weiteres in eine Web-Anwendung integrierbar. Es gibt zwar WebAssembly-Ports von PDFium (etwa pdfium-wasm), die sind aber experimentell und werden nicht von Google offiziell maintained.
pdf.js in der Praxis: Akzeptierte Limits
pdf.js ist keine perfekte PDF-Implementation. Einige Limits sind seit Jahren bekannt und werden vom Mozilla-Team bewusst akzeptiert. Komplexe Vektor-Grafiken mit vielen Bezier-Kurven rendern langsamer als in nativen Readern. Bestimmte Adobe-spezifische Schriften-Encodings werden nicht zu 100 Prozent unterstützt. JavaScript-Aktionen in PDFs (interaktive Formulare, Buttons) werden nur teilweise ausgeführt, aus Sicherheits-Gründen.
Für die meisten Anwendungsfälle sind diese Limits irrelevant. Für PDF-Konvertierungs-Tools wie unseres reicht die Rendering-Funktionalität voll aus, weil wir keine interaktiven Formulare brauchen. Für E-Commerce-Anwendungen mit ausfüllbaren Bestellscheinen wäre eine andere Lösung sinnvoller.
Architektur: Web Workers und Async-API
Das technische Herzstück von pdf.js ist die saubere Trennung zwischen Worker und Main-Thread. Wenn man getDocument(arrayBuffer) aufruft, schickt die Main-Thread-API den Buffer an den Worker. Der Worker parst die PDF-Struktur, baut einen Page-Tree auf und gibt einen Proxy zurück. Wenn die Anwendung doc.getPage(1) aufruft, lädt der Worker die Seite, parst ihren Content-Stream und gibt einen PDFPageProxy zurück.
Das eigentliche Rendering passiert dann im Main-Thread, weil Canvas-APIs in Web Workers (mit Ausnahme von OffscreenCanvas in modernen Browsern) nicht verfügbar sind. Die Render-Operationen sind aber dünn, weil der Worker die Content-Streams schon vorgeparst und die nötigen Daten als Drawing-Commands übergibt.
Diese Architektur hat zwei Vorteile: erstens läuft das CPU-intensive Parsing parallel zum UI, sodass Scroll-Events und Animationen flüssig bleiben. Zweitens kann der Worker pausiert und neugestartet werden, ohne den Tab zu verlieren. Bei Crashes im Worker fängt sich pdf.js selbst auf, was bei Plugin-Architekturen unmöglich war.
Was pdf.js für unsere Tools bedeutet
Auf pdfkonvertieren.de nutzen wir pdfjs-dist für vier von sieben Konvertierungs-Tools: PDF zu JPG, PDF zu PNG, PDF zu TXT und die Vorschau im PDF-Zusammenfügen-Tool. Ohne pdf.js wären diese Tools nicht ohne Server möglich. Wir würden entweder einen Server brauchen, um PDFs zu rendern (mit allen DSGVO-Implikationen), oder wir müssten ein kommerzielles SDK wie PDFTron lizenzieren (mit fünfstelligen Jahreskosten).
Die Apache-2.0-Lizenz von pdf.js erlaubt uns die kommerzielle Nutzung ohne Lizenzgebühren. Wir müssen nur die Lizenz-Datei mit ausliefern, was wir über pnpm-Standard-Behandlung automatisch tun. Die Library wird laufend gepflegt, monatliche Releases bringen Bug-Fixes und Performance-Verbesserungen.
Sicherheitsaspekte und Sandboxing
Ein zentrales Argument für pdf.js war von Anfang an die Sicherheit. Browser-Plugins liefen außerhalb der Browser-Sandbox und konnten bei Bug-Ausnutzung direkten System-Zugriff bekommen. pdf.js läuft als JavaScript im Browser-Sandbox-Prozess mit denselben Rechten wie jede andere Webseite, also stark eingeschränkt. Auch wenn ein Bug in pdf.js ausgenutzt würde, könnte der Angreifer nur das tun, was Browser-JavaScript ohnehin darf: kein File-System-Zugriff, keine System-API-Calls.
Mozilla pflegt zudem ein striktes Security-Response-Programm. Kritische Vulnerabilities werden meist innerhalb von 14 Tagen gepatcht. Die Open-Source-Natur erlaubt unabhängige Audits, was die Code-Qualität langfristig hochhält. Das Mozilla Security Bug Bounty Program zahlt für gemeldete Sicherheitslücken in pdf.js zwischen 500 und 7500 US-Dollar, je nach Schwere.
Im Vergleich dazu hatte Adobe Reader 2009 mehr als 60 CVE-Einträge mit kritischer Bewertung, viele wochenlang unpatcht. Diese Sicherheits-Bilanz war einer der wichtigsten Treiber für Mozillas Entscheidung, pdf.js zu starten.
Was hängenbleibt
Mozillas pdf.js startete im Mai 2011 als Forschungsprojekt von Andreas Gal mit dem Ziel, das Adobe-Acrobat-Plugin obsolet zu machen. Der erste Public-Beta-Post auf dem Mozilla-Hacks-Blog erschien am 14. Juni 2011. Mit Firefox 19 (19. Februar 2013) wurde pdf.js zum Default-PDF-Renderer und ersetzte das Plugin. Heute läuft pdf.js als pdfjs-dist auf npm millionenfach pro Woche und ist Standard für Browser-PDF-Tools. Die Apache-2.0-Lizenz erlaubt kommerzielle Nutzung ohne Gebühren. Auf pdfkonvertieren.de nutzen wir pdf.js für jedes Tool, das ein PDF lesen oder rendern muss. Ohne diese Library wäre ein Browser-only-PDF-Tool dieser Art nicht ohne Weiteres machbar.
FAQ
Häufige Fragen
Wer hat pdf.js gestartet?
Andreas Gal, damals Forschungsleiter bei Mozilla, startete pdf.js im Mai 2011 mit einem kleinen Team. Der erste Public-Beta-Post auf dem Mozilla-Hacks-Blog erschien am 14. Juni 2011 unter dem Titel 'Why pdf.js'. Das Ziel war ein reiner JavaScript-PDF-Renderer ohne Plugin und ohne native Code-Komponente. Gal arbeitete später bei Mozilla auch an Firefox OS und gründete dann Silk Labs.
Warum wollte Mozilla das Adobe-Plugin loswerden?
Browser-Plugins waren 2011 die größte Sicherheits-Lücke. Adobe Acrobat hatte 2009 und 2010 dutzende kritischer Zero-Day-Vulnerabilities. Mozilla wollte die Angriffsfläche reduzieren und gleichzeitig die Performance verbessern, weil Plugins immer Synchron-Calls zwischen Browser und Plugin-Prozess erfordern. Ein nativer JavaScript-Renderer läuft direkt im Sandbox-Prozess des Browsers, ohne Inter-Process-Communication.
Seit wann ist pdf.js in Firefox integriert?
Firefox 19, veröffentlicht am 19. Februar 2013, war die erste Version mit pdf.js als Default-PDF-Viewer. Vorher musste man pdf.js als Addon installieren. Mit Firefox 19 verschwand die Notwendigkeit für das Adobe-Plugin komplett. Chrome zog ungefähr zur gleichen Zeit nach, allerdings mit dem hauseigenen PDFium statt pdf.js.
Was bedeutet pdfjs-dist?
`pdfjs-dist` ist die npm-Distribution des pdf.js-Projekts. Sie enthält die fertig kompilierten Builds (Main-Bundle plus Worker-Datei) zum Einbetten in fremde Webseiten und Anwendungen. Wer nicht Firefox-intern arbeitet, sondern eigene Web-Apps oder Tools baut, verwendet `pdfjs-dist`. Die Library liegt auf npm mit aktuell mehreren Millionen wöchentlicher Downloads.
Wie performant ist pdf.js verglichen mit nativem PDF-Rendering?
Reines JavaScript ist langsamer als kompilierter C++-Code. PDFium (Chrome) oder Adobe Acrobat rendern komplexe PDFs etwa 2 bis 3 mal schneller als pdf.js. Bei einfachen Text-PDFs ist der Unterschied unter 50 Millisekunden pro Seite und nicht wahrnehmbar. Bei sehr komplexen PDFs mit vielen Vektor-Pfaden, eingebetteten Fonts und Transparenz kann pdf.js spürbar langsamer sein. Die Kompromiss-Bilanz fiel für Mozilla klar zugunsten von Sicherheit und Wartbarkeit aus.
Quellen
Worauf dieser Ratgeber sich stützt
Verwandte Ratgeber