Back

Afficher des PDF dans des applications Vue 3

Afficher des PDF dans des applications Vue 3

Intégrer un PDF dans une SPA Vue 3 semble simple—jusqu’à ce que vous rencontriez votre première erreur CORS, découvriez que le navigateur l’affiche différemment sur Safari, ou réalisiez que votre document de 200 pages bloque le thread principal. Cet article couvre les trois approches pratiques que les développeurs utilisent réellement pour afficher des PDF dans Vue 3, avec des compromis honnêtes pour chacune.

Points clés à retenir

  • Les trois principales approches pour afficher des PDF dans Vue 3 sont les intégrations natives du navigateur (<iframe>/<embed>), l’intégration directe de PDF.js, et les composants wrapper spécifiques à Vue.
  • Les intégrations natives n’ont aucun coût en termes de taille de bundle mais n’offrent aucun contrôle sur le style, les barres d’outils ou la cohérence entre navigateurs.
  • PDF.js vous donne un contrôle total sur le rendu mais ajoute une charge client notable—chargez-le en lazy loading avec import() dynamique pour maintenir des temps de chargement initial rapides.
  • Les wrappers Vue PDF comme vue-pdf-embed réduisent considérablement le code répétitif au prix d’une certaine flexibilité de personnalisation.
  • La configuration correcte du worker et le lazy loading sont les deux étapes qui préviennent les problèmes les plus courants liés aux PDF dans les applications Vue.

Les trois approches principales

1. Intégration native du navigateur : <iframe> ou <embed>

Le moyen le plus rapide d’afficher un PDF à l’écran est de le confier au moteur de rendu PDF intégré du navigateur.

<template>
  <iframe
    :src="pdfUrl"
    width="100%"
    height="700px"
    style="border: none"
  />
</template>

<script setup lang="ts">
const pdfUrl = '/documents/report.pdf'
</script>

Quand cela fonctionne bien : Outils internes, tableaux de bord d’administration, ou tout contexte où la cohérence de l’interface utilisateur n’est pas critique et où le PDF est servi depuis la même origine.

Les vraies limitations :

  • Aucun contrôle sur la barre d’outils, les contrôles de zoom ou le thème
  • Le comportement varie selon les navigateurs—Chrome, Firefox et Safari affichent chacun différemment
  • Les navigateurs mobiles téléchargent souvent le fichier au lieu de l’afficher en ligne
  • L’état de chargement est invisible pour votre composant Vue, vous ne pouvez donc pas afficher un spinner ou gérer les erreurs de manière élégante

Si vous chargez un PDF depuis un domaine différent, le navigateur bloquera la requête sauf si le serveur envoie les en-têtes Access-Control-Allow-Origin corrects. Un endpoint proxy de même origine sur votre backend est la solution la plus propre.


2. PDF.js avec Vue 3 : Intégration directe

PDF.js est le moteur de rendu PDF open-source de Mozilla. Depuis la série de versions 5.x, il est distribué comme un package ESM-first. Vous importez depuis build/pdf.mjs et chargez un worker séparé (pdf.worker.mjs) pour maintenir le rendu hors du thread principal.

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>

Ce que vous gagnez : Contrôle total sur le rendu, la navigation entre pages, le zoom et le thème. PDF.js prend en charge les annotations standard et les champs AcroForm, bien que le comportement des formulaires et annotations puisse dépendre de la configuration du rendu.

Ce que vous devez savoir :

  • Le package pdfjs-dist ajoute une charge notable à votre bundle client. Utilisez import() dynamique pour le charger en lazy loading.
  • Les formulaires basés sur XFA (courants dans les anciens PDF gouvernementaux) ont un support limité et peuvent ne pas s’afficher correctement.
  • Pour les documents volumineux, PDF.js peut récupérer les PDF par morceaux lorsque le serveur prend en charge les requêtes HTTP range (Accept-Ranges: bytes), ce qui peut améliorer les performances perçues pour les fichiers volumineux.
  • La configuration du worker est le problème de configuration le plus courant dans les projets Vite. Le pattern new URL(..., import.meta.url) montré ci-dessus résout correctement le chemin du worker au moment du build.

3. Wrappers Vue PDF

Plusieurs composants Vue 3 maintenus encapsulent PDF.js et exposent une API de composant plus simple. vue-pdf-embed est une option activement maintenue qui gère la configuration du worker, le rendu des pages et les mises à jour réactives des props pour vous.

<script setup lang="ts">
import VuePdfEmbed from 'vue-pdf-embed'
</script>

<template>
  <VuePdfEmbed source="/documents/report.pdf" />
</template>

Le compromis est un contrôle moins granulaire en échange de beaucoup moins de code répétitif. Ces wrappers conviennent bien lorsque vous avez besoin d’un visualiseur PDF Vue 3 fonctionnel rapidement et que vous n’avez pas besoin de personnaliser le pipeline de rendu.

Note : Certains packages plus anciens comme vue3-pdf-app ne sont plus activement maintenus. Évaluez le statut de maintenance et la compatibilité de tout wrapper avec les bundlers modernes comme Vite avant de l’adopter.


Choisir la bonne approche

ApprocheCoût du bundlePersonnalisationIdéal pour
<iframe> / <embed>0 KoAucuneIntégrations rapides, fichiers same-origin
PDF.js directCharge client-sideTotaleVisualiseurs personnalisés, docs volumineux
Wrapper VueSimilaire à PDF.jsModéréeConfiguration rapide, cas d’usage standards

Conclusion

Pour la plupart des applications Vue 3, la décision est simple : utilisez <iframe> pour les intégrations same-origin simples, optez pour un wrapper Vue maintenu lorsque vous avez besoin d’un visualiseur fonctionnel sans beaucoup de configuration, et intégrez PDF.js directement lorsque vous avez besoin d’un contrôle total sur le rendu, la navigation ou les performances pour les documents volumineux. Quel que soit le chemin choisi, configurez correctement le worker PDF.js et chargez la bibliothèque en lazy loading. Ces deux étapes à elles seules préviendront les problèmes les plus courants que rencontrent les développeurs lors de l’intégration de PDF dans les applications Vue.

FAQ

Le navigateur bloque les requêtes PDF cross-origin sauf si le serveur inclut l'en-tête Access-Control-Allow-Origin dans sa réponse. La solution la plus fiable est de configurer un endpoint proxy de même origine sur votre propre backend qui récupère le PDF et le sert à votre application Vue. Cela évite de dépendre de configurations de serveurs tiers que vous ne contrôlez peut-être pas.

Vite gère les URL d'assets différemment de Webpack. Utilisez le pattern new URL avec import.meta.url pour résoudre le chemin du worker au moment du build. Par exemple, définissez workerSrc sur new URL de pdfjs-dist/build/pdf.worker.mjs avec import.meta.url, puis appelez toString. Cela garantit que Vite traite correctement le fichier worker pendant les builds de développement et de production.

Oui. Après avoir chargé le document, bouclez de 1 à pdf.numPages, appelez getPage pour chaque numéro de page, créez un élément canvas pour chacune, et affichez-les séquentiellement ou en parallèle. Pour les très gros documents, envisagez de n'afficher que les pages visibles et de charger les autres au défilement pour éviter une utilisation élevée de la mémoire et des temps de rendu initial lents.

Utilisez un wrapper comme vue-pdf-embed si vous avez besoin d'un visualiseur standard avec une configuration minimale et ne nécessitez pas de personnalisation approfondie. Intégrez PDF.js directement lorsque vous avez besoin d'un contrôle total sur le rendu, la navigation personnalisée, le thème ou les optimisations de performances comme le chargement lazy des pages. Les wrappers ajoutent une couche fine au-dessus de PDF.js, donc le coût du bundle est presque identique dans les deux cas.

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.

OpenReplay