Migrating from PDF.js to Syncfusion React PDF Viewer
26 Mar 202610 minutes to read
This guide explains how to migrate an existing PDF.js implementation to the Syncfusion React PDF Viewer, covering architectural differences, feature mapping, and required code changes.
Overview
PDF.js is a low-level JavaScript library that focuses on rendering PDF pages using HTML canvas and requires developers to manually implement navigation, zooming, text selection, annotations, and UI controls.
Syncfusion React PDF Viewer is a fully featured, high-level React component that provides built-in rendering, UI, interaction tools, and performance optimizations out of the box.
Architecture notes
This guide shows a migration path from a low-level canvas-based renderer (PDF.js) to the PdfViewerComponent used by Syncfusion. Key migration considerations:
- Rendering model: PDF.js exposes page and canvas rendering APIs requiring manual drawing and layout, while
PdfViewerComponentmanages rendering, paging, and UI internally. - UI and tooling: PDF.js implementations typically implement custom toolbars and controls; Syncfusion exposes a configurable toolbar and injectable services for features like annotations, search, and forms.
- Event model: PDF.js uses promises and page/render callbacks; use
PdfViewerComponentevents such asdocumentLoad,pageRenderComplete, andpageChangeto mirror life cycle hooks. - Persistence and integration: Rework custom annotation/form persistence to the Syncfusion export/import APIs when migrating.
Installation
PDF.js
npm install pdfjs-distSyncfusion React PDF Viewer
npm install @syncfusion/ej2-react-pdfviewerRendering a PDF
PDF.js Example
import * as pdfjsLib from 'pdfjs-dist';
pdfjsLib.getDocument('sample.pdf').promise.then(pdf => {
pdf.getPage(1).then(page => {
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
const viewport = page.getViewport({ scale: 1.5 });
canvas.height = viewport.height;
canvas.width = viewport.width;
page.render({ canvasContext: context, viewport });
});
});Syncfusion React PDF Viewer
import * as ReactDOM from 'react-dom';
import * as React from 'react';
import {
PdfViewerComponent,
Toolbar,
Magnification,
Navigation,
Annotation,
TextSearch,
FormFields,
Inject,
} from '@syncfusion/ej2-react-pdfviewer';
export function App() {
return (
<PdfViewerComponent
id="container"
documentPath="https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf"
resourceUrl="https://cdn.syncfusion.com/ej2/31.2.2/dist/ej2-pdfviewer-lib"
style={{ height: '640px' }}
>
<Inject
services={[
Toolbar,
Magnification,
Navigation,
Annotation,
TextSearch,
FormFields,
]}
/>
</PdfViewerComponent>
);
}
const root = ReactDOM.createRoot(document.getElementById('sample'));
root.render(<App />);Feature checklist (Syncfusion)
Event Handling
PDF.js
page.render().promise.then(() => console.log('Rendered'));Syncfusion Viewer
Check Syncfusion Events Guide to know more about event handling in Syncfusion React PDF Viewer.
<PdfViewerComponent
documentLoad={() => console.log('Document loaded')}
pageChange={(args) => console.log(args.currentPage)}
/>Tutorial: Step-by-step migration
This minimal tutorial shows a focused migration path from a canvas-based PDF.js renderer to the PdfViewerComponent.
1) Project preparations
- Remove existing
pdf js-distusage from the components you will replace. Keep a working branch so you can compare behavior. - Install Syncfusion React PDF Viewer:
npm install @syncfusion/ej2-react-pdfviewerAdd CSS references and local resources
Syncfusion PDF Viewer requires several CSS packages and (for local hosting) the ej2-pdfviewer-lib resources. Add the CSS imports to src/index.css and copy the ej2-pdfviewer-lib folder into your public directory if you host resources locally.
@import '../node_modules/@syncfusion/ej2-base/styles/material.css';
@import '../node_modules/@syncfusion/ej2-buttons/styles/material.css';
@import '../node_modules/@syncfusion/ej2-dropdowns/styles/material.css';
@import '../node_modules/@syncfusion/ej2-inputs/styles/material.css';
@import '../node_modules/@syncfusion/ej2-navigations/styles/material.css';
@import '../node_modules/@syncfusion/ej2-popups/styles/material.css';
@import '../node_modules/@syncfusion/ej2-splitbuttons/styles/material.css';
@import "../node_modules/@syncfusion/ej2-pdfviewer/styles/material.css";To host local resources, copy the ej2-pdfviewer-lib folder:
cp -R ./node_modules/@syncfusion/ej2-pdfviewer/dist/ej2-pdfviewer-lib public/ej2-pdfviewer-libOr set resourceUrl to the Syncfusion CDN (example shown later).
2) Replace the renderer component
- Before (file:
src/components/PdfCanvas.js— simplified):
import * as pdfjsLib from 'pdfjs-dist';
export default function PdfCanvas() {
// existing canvas-based initialization and render loop
}- After (file:
src/components/PdfViewer.jsx):
import * as ReactDOM from 'react-dom';
import * as React from 'react';
import {
PdfViewerComponent,
Toolbar,
Magnification,
Navigation,
Annotation,
TextSearch,
FormFields,
Inject,
} from '@syncfusion/ej2-react-pdfviewer';
export function App() {
return (
<PdfViewerComponent
id="container"
documentPath="https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf"
resourceUrl="https://cdn.syncfusion.com/ej2/31.2.2/dist/ej2-pdfviewer-lib"
style={{ height: '640px' }}
>
<Inject
services={[
Toolbar,
Magnification,
Navigation,
Annotation,
TextSearch,
FormFields,
]}
/>
</PdfViewerComponent>
);
}
const root = ReactDOM.createRoot(document.getElementById('sample'));
root.render(<App />);3) Wire resources and service URLs
- If you previously used worker files for PDF.js, decide whether to use Syncfusion’s CDN
resourceUrlor host the Syncfusion library files yourself. Example:
<PdfViewerComponent
id="container"
documentPath="https://cdn.syncfusion.com/content/pdf/pdf-succinctly.pdf"
resourceUrl="https://cdn.syncfusion.com/ej2/31.2.2/dist/ej2-pdfviewer-lib"
style=
>
<Inject
services={[
Toolbar,
Magnification,
Navigation,
Annotation,
TextSearch,
FormFields,
]}
/>
</PdfViewerComponent>4) Migrate interactions and tests
- Replace manual navigation, zoom, and annotation calls with the corresponding
PdfViewerComponentprops and methods. - Add simple integration checks: open a document, navigate to a page, add an annotation, search text, and save/export.
API mapping: common PDF.js → Syncfusion equivalents
| PDF.js | Reason / Syncfusion equivalent |
|---|---|
pdfjsLib.getDocument(url).promise |
Document loading handled by PdfViewerComponent via documentPath or load() method. |
pdf.getPage(n) |
Viewer exposes page events and getPageInfo(pageIndex); page lifecycle is surfaced via pageRenderInitiate / pageRenderComplete events. |
page.render({ canvasContext, viewport }) |
Rendering is internal — replace with PdfViewerComponent rendering; no manual canvas drawing required. |
page.getTextContent() |
Use extractText(pageIndex, options) or enable enableTextSearch/enableTextSelection for built-in search/selection. |
| Custom toolbar buttons controlling canvas | Use Toolbar service, or add custom toolbar items and handle toolbarClick events. |
| Custom annotation storage | Use addAnnotation, exportAnnotation, importAnnotation, and exportAnnotationsAsBase64String methods. |
| Manual print/download flows | Use download() and built-in Print service. |
| Page render promise | Listen to pageRenderComplete / documentLoad events for lifecycle hooks. |
Expanded Migration Checklist (concrete steps)
- Create a feature branch and add automated/manual smoke tests for existing PDF.js behavior.
- Remove
pdfjs-distimport and any canvas DOM elements dedicated to PDF rendering. - Add
@syncfusion/ej2-react-pdfviewertopackage.jsonand runnpm install. - Replace the rendering component file(s): create
PdfViewer.jsxand migrate app routes/imports to use it. - Ensure required CSS and assets are included (Syncfusion component styles are usually in the package or CDN). If you use a CDN
resourceUrl, add it toPdfViewerComponentasresourceUrl. - Inject only the services you need (Toolbar, Annotation, TextSearch, Forms) to keep bundle size minimal.
- Migrate event handlers:
- PDF.js:
getDocument().then(...).then(page => page.render().promise.then(...))→ Syncfusion:documentLoad,pageRenderComplete,pageChangeevents. - For form interactions, map existing input handlers to
formFieldevents likeformFieldClickandvalidateFormFields.
- PDF.js:
- Migrate search and text extraction to
enableTextSearchandextractText()where required. - Migrate annotations using
addAnnotation,importAnnotation, and persistence APIs. Verify serialization format if you persist annotations to your backend. - Update toolbar and UI to use
ToolbarComponentorPdfViewerComponent’s built-in toolbar (toggling viaenableToolbar). - Test on target browsers and configurations; verify performance for large PDFs.
- Remove stale code paths and unit tests specific to PDF.js implementation.
NOTE
To know more about available Features in Syncfusion React PDF Viewer. Check PDF Viewer Key Features
Reference: key Syncfusion PdfViewerComponent methods & events
- PdfViewerComponent API index
- load() — programmatically load a PDF.
- download() — trigger download of current document.
- addAnnotation(annotation: any) — add an annotation programmatically.
- exportAnnotation(annotationDataFormat) / exportAnnotationsAsBase64String(): — export annotations for persistence.
- extractText(pageIndex: number, options?: any): — extract text and coordinates.
- Events: documentLoad, pageRenderComplete, pageChange, annotationAdd, annotationRemove, toolbarClick.