What the viewer does for you
- One worker. Every document shares a single pdf.js worker (set
configurePdf({ sharedWorker: false })to opt out). - Exact, cheap layout. All page shells exist from the start with their real size, so scroll height and jumps are exact; only pages within
overscanviewport heights get a bitmap. - Priority scheduler. Visible pages render first, nearby pages next, thumbnails last. Work for pages that scroll away is cancelled, and re-queuing a page replaces its pending job.
- Zoom without re-layout storms. A zoom frame changes one CSS variable (
--pdf-scale); the stretched bitmap stays until the sharp render lands. Text layers follow through CSS and are re-measured once zoom settles. - Sharp zoom-ins. Zoomed-out pages render at up to 2× (
oversampling), and a page stretched past 1.35× during a long zoom is refreshed once. - Bitmap cache. Pages that scroll away keep their bitmap in a shared LRU cache (
configurePdf({ bitmapCacheBytes }), default 192 MB,0disables), so scrolling back or changing columns redraws instantly. - Level of detail. Pages narrower than
detailMinWidth(260 CSS px) — thumbnail-sized spreads when zoomed out — skip their text layer and text indexing, so four-per-row layouts stay smooth. - Cached analysis.
PaperStateaccepts acache(KeyValueStore, e.g.indexedDbStore('papers')): analysis results are stored by document fingerprint and reopened papers skip analysis. - Capped bitmaps.
maxCanvasPixels(16M device pixels) bounds memory per page at high zoom. - Shared text. Page text is extracted and indexed once, then shared by the text layer, find, selection, annotations and paper analysis.
- Thumbnails are rendered lazily, at low priority, and cached per document.
Tuning
Research-paper analysis
Paper.Root analyses typical papers in 0.2–0.5 s; plot-heavy papers whose operator lists are expensive can take several seconds. Pass auto={false} and call paper.analyze() when the user opens a paper panel if you want to defer it.