Le contexte
Le lecteur d'annales de baccalaureat.sn repose sur @react-pdf-viewer, monté en îlot React dans une page Twig. En reconstruisant la feature, j'ai enchaîné trois bugs distincts qui se masquaient l'un l'autre — chaque correctif révélait le suivant. Récit dans l'ordre du diagnostic.
Bug 1 — Le viewer qui refuse de démarrer : versions pdfjs-dist
Premier symptôme, dès le montage : erreur de worker et viewer vide. La cause était dans le package.json : @react-pdf-viewer/core déclare une plage stricte de versions compatibles de pdfjs-dist, et npm avait résolu une version plus récente que ce que la lib supportait.
npm ls pdfjs-dist
# └── pdfjs-dist@3.11.174 ← installé
# @react-pdf-viewer/core requiert ^2.16.105 || ^3.0.279 (API compatible)
pdf.js casse régulièrement son API interne entre versions mineures — la plage déclarée par le viewer n'est pas décorative. Correctif : épingler une version testée compatible.
npm install pdfjs-dist@3.4.120 --save-exact
Le --save-exact est volontaire : pas de ^ qui laisserait npm re-dériver vers une version incompatible au prochain install.
Bug 2 — Parfait en local, mort en prod : le worker sur CDN
Viewer fonctionnel en local... et page blanche en production. La différence : le worker pdf.js était chargé depuis unpkg.
// AVANT : dépendance runtime à un CDN externe
const WORKER_URL = 'https://unpkg.com/pdfjs-dist@3.4.120/build/pdf.worker.min.js';
En prod, entre la Content-Security-Policy du site et les aléas du CDN, le worker ne se chargeait pas — et sans worker, pdf.js ne rend rien. La solution robuste : servir le worker soi-même, depuis ses propres assets, avec Vite qui résout l'URL au build :
// APRÈS : le worker est un asset local, hashé et servi par mon propre domaine
import workerUrl from 'pdfjs-dist/build/pdf.worker.min.js?url';
<Worker workerUrl={workerUrl}>
<Viewer fileUrl={pdfUrl} />
</Worker>
Le suffixe ?url demande à Vite de traiter le fichier comme un asset et d'en renvoyer l'URL finale. Plus de CDN tiers dans la boucle : même origine, même cache, même politique de sécurité que le reste du site.
Bug 3 — Une seule page visible, document décalé : l'overflow parent
Dernier bug, le plus sournois : le PDF s'affiche enfin, mais une seule page, impossible de défiler, et le document apparaissait décalé dans son cadre. Aucune erreur console. Le coupable n'était pas dans le viewer — il était dans mon CSS :
/* AVANT : le conteneur de la page, écrit des semaines plus tôt */
.lecteur-container {
overflow: hidden; /* posé « pour la propreté » du layout */
height: 80vh;
}
@react-pdf-viewer gère son propre conteneur de scroll virtuel : il rend les pages au fur et à mesure du défilement. Un overflow: hidden sur un parent coupe ce mécanisme — le viewer croit que rien ne défile, donc ne rend jamais les pages suivantes. Correctif : retirer tout overflow: hidden des ancêtres du viewer et lui donner une hauteur explicite, puis le laisser gérer son scroll interne.
/* APRÈS : le viewer est seul maître de son défilement */
.lecteur-container {
height: 80vh;
/* plus d'overflow: hidden ici ni sur aucun parent du viewer */
}
Ce que je retiens
- Les plages de versions de
pdfjs-distdéclarées par @react-pdf-viewer sont strictes pour de bonnes raisons — épingler avec--save-exactévite les régressions silencieuses. - Un worker chargé depuis un CDN tiers est une dépendance runtime cachée : en prod, CSP et disponibilité du CDN deviennent VOS problèmes. L'import Vite
?urlramène tout en local. - Quand un composant à scroll virtuel ne rend qu'une partie de son contenu sans erreur, chercher un
overflow: hiddenchez ses ancêtres avant de suspecter la lib. - Trois bugs imbriqués = corriger dans l'ordre où ils se révèlent, un à la fois, en validant chaque étape — jamais les trois en parallèle.