Il contesto

Il lettore di prove degli anni precedenti di baccalaureat.sn si basa su @react-pdf-viewer, montato come isola React in una pagina Twig. Ricostruendo la feature, ho incontrato tre bug distinti che si mascheravano a vicenda — ogni correzione rivelava la successiva. Racconto nell'ordine della diagnosi.

Bug 1 — Il viewer che rifiuta di avviarsi: versioni pdfjs-dist

Primo sintomo, fin dal montaggio: errore di worker e viewer vuoto. La causa era nel package.json: @react-pdf-viewer/core dichiara un intervallo rigido di versioni compatibili di pdfjs-dist, e npm aveva risolto una versione più recente di quella supportata dalla lib.

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 rompe regolarmente la sua API interna tra versioni minori — l'intervallo dichiarato dal viewer non è decorativo. Correzione: fissare una versione testata e compatibile.

npm install pdfjs-dist@3.4.120 --save-exact

Il --save-exact è volontario: niente ^ che lascerebbe npm ri-derivare verso una versione incompatibile al prossimo install.

Bug 2 — Perfetto in locale, morto in prod: il worker su CDN

Viewer funzionante in locale... e pagina bianca in produzione. La differenza: il worker pdf.js era caricato da unpkg.

// AVANT : dépendance runtime à un CDN externe
const WORKER_URL = 'https://unpkg.com/pdfjs-dist@3.4.120/build/pdf.worker.min.js';

In prod, tra la Content-Security-Policy del sito e gli imprevisti del CDN, il worker non si caricava — e senza worker, pdf.js non renderizza nulla. La soluzione robusta: servire il worker da soli, dai propri asset, con Vite che risolve l'URL al 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>

Il suffisso ?url chiede a Vite di trattare il file come asset e di restituirne l'URL finale. Niente più CDN di terze parti nel giro: stessa origine, stessa cache, stessa politica di sicurezza del resto del sito.

Bug 3 — Una sola pagina visibile, documento sfalsato: l'overflow del parent

Ultimo bug, il più subdolo: il PDF finalmente si visualizza, ma una sola pagina, impossibile scorrere, e il documento appariva sfalsato nella sua cornice. Nessun errore in console. Il colpevole non era nel viewer — era nel mio 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 gestisce il proprio contenitore di scroll virtuale: renderizza le pagine man mano che si scorre. Un overflow: hidden su un parent interrompe questo meccanismo — il viewer crede che nulla scorra, quindi non renderizza mai le pagine successive. Correzione: rimuovere ogni overflow: hidden dagli antenati del viewer e dargli un'altezza esplicita, poi lasciargli gestire il proprio scroll interno.

/* 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 */
}

Cosa mi porto via

  • Gli intervalli di versioni di pdfjs-dist dichiarati da @react-pdf-viewer sono rigidi per buone ragioni — fissare con --save-exact evita regressioni silenziose.
  • Un worker caricato da un CDN di terze parti è una dipendenza runtime nascosta: in prod, CSP e disponibilità del CDN diventano i VOSTRI problemi. L'import Vite ?url riporta tutto in locale.
  • Quando un componente a scroll virtuale renderizza solo una parte del suo contenuto senza errori, cercare un overflow: hidden tra i suoi antenati prima di sospettare la lib.
  • Tre bug annidati = correggere nell'ordine in cui si rivelano, uno alla volta, validando ogni passo — mai tutti e tre in parallelo.