Install pdfcanvas
The package ships TypeScript and ESM. Three files have to be served from your own origin: the PDF.js worker, its supporting assets, and the PDFium WebAssembly binary.
1. Install
npm install pdfcanvas pdfjs-dist pdf-lib @embedpdf/pdfiumThe three peer packages are declared, but installing them explicitly keeps worker paths and lockfiles obvious.
2. Copy the assets
Copy these into a public folder that your bundler serves as-is.
build/pdf.worker.min.mjs -> public/pdfjs/pdf.worker.min.mjs
cmaps/ -> public/pdfjs/cmaps/
standard_fonts/ -> public/pdfjs/standard_fonts/
wasm/ -> public/pdfjs/wasm/
@embedpdf/pdfium/dist/pdfium.wasm -> public/pdfium/pdfium.wasm
assets/fonts/ -> public/fonts/3. Mount the engine
import { PdfCanvas } from "pdfcanvas";
const pdf = new PdfCanvas(document.querySelector("#editor")!, {
workerSrc: "/pdfjs/pdf.worker.min.mjs",
cMapUrl: "/pdfjs/cmaps/",
standardFontDataUrl: "/pdfjs/standard_fonts/",
wasmUrl: "/pdfjs/wasm/",
pdfiumWasmUrl: "/pdfium/pdfium.wasm",
fontAssetsUrl: "/fonts/",
initialZoom: "fit-width",
});
await pdf.load(file);Bundler notes
- Vite: import the worker with ?url if you prefer the bundler to emit it.
- Next.js: the editor is client-only. Use dynamic import with ssr: false.
- The container needs a height. A flex child with min-height: 0 is the usual fix.
- Serve .wasm with application/wasm so the browser can stream-compile it.
Frequently asked questions
+Can I load the worker from a CDN?
Technically yes, but the library does not do it by default. A third-party CDN would see the requests your documents generate, which defeats the local-processing guarantee.
+Why is the PDFium file so large?
It is a complete PDF engine compiled to WebAssembly. It is fetched once, cached by the browser, and only needed for editing existing text.
+Do I need all the CMaps and standard fonts?
Only for PDFs that reference non-embedded fonts or CJK encodings. Shipping them avoids broken glyphs on those documents.