PDFs in Vue 3-Anwendungen anzeigen
Das Einbetten eines PDFs in eine Vue 3 SPA klingt zunächst unkompliziert – bis Sie auf Ihren ersten CORS-Fehler stoßen, feststellen, dass der Browser es in Safari anders rendert, oder merken, dass Ihr 200-seitiges Dokument den Main-Thread blockiert. Dieser Artikel behandelt die drei praktischen Ansätze, die Entwickler tatsächlich zum Anzeigen von PDFs in Vue 3 verwenden, mit ehrlichen Abwägungen für jeden Ansatz.
Wichtigste Erkenntnisse
- Die drei Hauptansätze zum Anzeigen von PDFs in Vue 3 sind native Browser-Embeds (
<iframe>/<embed>), direkte PDF.js-Integration und Vue-spezifische Wrapper-Komponenten. - Native Embeds kosten keine Bundle-Größe, bieten aber keine Kontrolle über Styling, Toolbars oder browserübergreifende Konsistenz.
- PDF.js gibt Ihnen volle Rendering-Kontrolle, fügt aber eine spürbare Client-seitige Payload hinzu – laden Sie es mit dynamischem
import()lazy, um die initialen Ladezeiten niedrig zu halten. - Vue-PDF-Wrapper wie
vue-pdf-embedreduzieren Boilerplate erheblich auf Kosten einer gewissen Anpassungsflexibilität. - Korrekte Worker-Konfiguration und Lazy Loading sind die beiden Schritte, die die häufigsten PDF-bezogenen Probleme in Vue-Apps verhindern.
Die drei Kernansätze
1. Natives Browser-Embed: <iframe> oder <embed>
Der schnellste Weg, ein PDF auf den Bildschirm zu bringen, besteht darin, es an den integrierten PDF-Renderer des Browsers zu übergeben.
<template>
<iframe
:src="pdfUrl"
width="100%"
height="700px"
style="border: none"
/>
</template>
<script setup lang="ts">
const pdfUrl = '/documents/report.pdf'
</script>
Wann es gut funktioniert: Interne Tools, Admin-Dashboards oder jeder Kontext, in dem UI-Konsistenz nicht kritisch ist und das PDF vom gleichen Origin bereitgestellt wird.
Die tatsächlichen Einschränkungen:
- Keine Kontrolle über die Toolbar, Zoom-Steuerung oder das Theming
- Das Verhalten variiert zwischen Browsern – Chrome, Firefox und Safari rendern jeweils unterschiedlich
- Mobile Browser laden die Datei oft herunter, anstatt sie inline anzuzeigen
- Der Ladezustand ist für Ihre Vue-Komponente unsichtbar, sodass Sie keinen Spinner anzeigen oder Fehler elegant behandeln können
Wenn Sie ein PDF von einer anderen Domain laden, blockiert der Browser die Anfrage, es sei denn, der Server sendet die korrekten Access-Control-Allow-Origin-Header. Ein Same-Origin-Proxy-Endpoint auf Ihrem Backend ist die sauberste Lösung.
2. PDF.js mit Vue 3: Direkte Integration
PDF.js ist Mozillas Open-Source-PDF-Rendering-Engine. Ab der 5.x-Release-Serie wird es als ESM-first-Paket ausgeliefert. Sie importieren aus build/pdf.mjs und laden einen separaten Worker (pdf.worker.mjs), um das Rendering vom Main-Thread fernzuhalten.
npm install pdfjs-dist
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import * as pdfjsLib from 'pdfjs-dist/build/pdf.mjs'
pdfjsLib.GlobalWorkerOptions.workerSrc = new URL(
'pdfjs-dist/build/pdf.worker.mjs',
import.meta.url
).toString()
const canvasRef = ref<HTMLCanvasElement | null>(null)
onMounted(async () => {
const pdf = await pdfjsLib.getDocument('/documents/report.pdf').promise
const page = await pdf.getPage(1)
const viewport = page.getViewport({ scale: 1.5 })
const canvas = canvasRef.value!
const ctx = canvas.getContext('2d')!
canvas.height = viewport.height
canvas.width = viewport.width
await page.render({ canvasContext: ctx, viewport }).promise
})
</script>
<template>
<canvas ref="canvasRef" />
</template>
Was Sie gewinnen: Volle Kontrolle über Rendering, Seitennavigation, Zoom und Theming. PDF.js unterstützt Standard-Annotationen und AcroForm-Felder, wobei das Formular- und Annotationsverhalten von der Rendering-Konfiguration abhängen kann.
Was Sie wissen sollten:
- Das
pdfjs-dist-Paket fügt eine spürbare Payload zu Ihrem Client-Bundle hinzu. Verwenden Sie dynamischesimport(), um es lazy zu laden. - XFA-basierte Formulare (häufig in älteren Behörden-PDFs) haben eingeschränkte Unterstützung und werden möglicherweise nicht korrekt gerendert.
- Bei großen Dokumenten kann PDF.js PDFs in Chunks abrufen, wenn der Server HTTP-Range-Requests unterstützt (
Accept-Ranges: bytes), was die wahrgenommene Performance bei großen Dateien verbessern kann. - Die Worker-Konfiguration ist das häufigste Setup-Problem in Vite-Projekten. Das oben gezeigte
new URL(..., import.meta.url)-Pattern löst den Worker-Pfad zur Build-Zeit korrekt auf.
Discover how at OpenReplay.com.
3. Vue-PDF-Wrapper
Mehrere gepflegte Vue 3-Komponenten wrappen PDF.js und bieten eine einfachere Komponenten-API. vue-pdf-embed ist eine aktiv gepflegte Option, die Worker-Setup, Seiten-Rendering und reaktive Prop-Updates für Sie übernimmt.
<script setup lang="ts">
import VuePdfEmbed from 'vue-pdf-embed'
</script>
<template>
<VuePdfEmbed source="/documents/report.pdf" />
</template>
Der Trade-off ist weniger granulare Kontrolle im Austausch für deutlich weniger Boilerplate. Diese Wrapper sind gut geeignet, wenn Sie schnell einen funktionierenden Vue 3-PDF-Viewer benötigen und die Rendering-Pipeline nicht anpassen müssen.
Hinweis: Einige ältere Pakete wie
vue3-pdf-appwerden nicht mehr aktiv gewartet. Bewerten Sie den Wartungsstatus und die Kompatibilität mit modernen Bundlern wie Vite, bevor Sie einen Wrapper einsetzen.
Den richtigen Ansatz wählen
| Ansatz | Bundle-Kosten | Anpassung | Am besten für |
|---|---|---|---|
<iframe> / <embed> | 0 KB | Keine | Schnelle Embeds, Same-Origin-Dateien |
| Direktes PDF.js | Client-seitige Payload | Voll | Custom Viewer, große Dokumente |
| Vue-Wrapper | Ähnlich wie PDF.js | Moderat | Schnelleres Setup, Standard-Use-Cases |
Fazit
Für die meisten Vue 3-Anwendungen ist die Entscheidung eindeutig: Verwenden Sie <iframe> für einfache Same-Origin-Embeds, greifen Sie zu einem gepflegten Vue-Wrapper, wenn Sie einen funktionierenden Viewer ohne viel Setup benötigen, und integrieren Sie PDF.js direkt, wenn Sie volle Kontrolle über Rendering, Navigation oder Performance bei großen Dokumenten benötigen. Welchen Weg Sie auch wählen, konfigurieren Sie den PDF.js-Worker korrekt und laden Sie die Bibliothek lazy. Diese beiden Schritte allein verhindern die häufigsten Probleme, auf die Entwickler beim Einbetten von PDFs in Vue-Apps stoßen.
FAQs
Der Browser blockiert Cross-Origin-PDF-Anfragen, es sei denn, der Server fügt den Access-Control-Allow-Origin-Header in seiner Antwort hinzu. Die zuverlässigste Lösung besteht darin, einen Same-Origin-Proxy-Endpoint auf Ihrem eigenen Backend einzurichten, der das PDF abruft und es an Ihre Vue-App ausliefert. Dies vermeidet die Abhängigkeit von Drittanbieter-Server-Konfigurationen, die Sie möglicherweise nicht kontrollieren.
Vite behandelt Asset-URLs anders als Webpack. Verwenden Sie das new URL mit import.meta.url-Pattern, um den Worker-Pfad zur Build-Zeit aufzulösen. Setzen Sie beispielsweise workerSrc auf new URL von pdfjs-dist/build/pdf.worker.mjs mit import.meta.url und rufen Sie dann toString auf. Dies stellt sicher, dass Vite die Worker-Datei sowohl während der Entwicklung als auch in Production-Builds korrekt verarbeitet.
Ja. Nach dem Laden des Dokuments loopen Sie von 1 bis pdf.numPages, rufen getPage für jede Seitennummer auf, erstellen ein Canvas-Element für jede Seite und rendern sie sequenziell oder parallel. Bei sehr großen Dokumenten sollten Sie erwägen, nur die sichtbaren Seiten zu rendern und andere beim Scrollen zu laden, um hohen Speicherverbrauch und langsame initiale Render-Zeiten zu vermeiden.
Verwenden Sie einen Wrapper wie vue-pdf-embed, wenn Sie einen Standard-Viewer mit minimalem Setup benötigen und keine tiefgreifende Anpassung erfordern. Integrieren Sie PDF.js direkt, wenn Sie volle Kontrolle über Rendering, benutzerdefinierte Navigation, Theming oder Performance-Optimierungen wie Lazy Page Loading benötigen. Wrapper fügen eine dünne Schicht über PDF.js hinzu, sodass die Bundle-Kosten in beiden Fällen nahezu identisch sind.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.