Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

react-native-pdf-jsi

126punith1.8kMIT4.2.2TypeScript support: included

🚀 Ultra-fast React Native PDF viewer with JSI (JavaScript Interface) integration for maximum performance. Features lazy loading, smart caching, progressive loading, and zero-bridge overhead operations. Perfect for large PDF files with 30-day persistent c

react-native-pdf, react-native-pdf-viewer, react-native-pdf-jsi, react-native-pdf-enhanced, pdf-viewer, pdf-reader, pdf-view, react-component, react-native, react-native-module, react-native-library, android, ios, windows, pdf, view, viewer, jsi, javascript-interface, performance, enhanced, native, bridge, high-performance, fast-pdf, lazy-loading, smart-caching, progressive-loading, memory-optimization, zero-bridge, native-module, cross-platform, mobile, document-viewer, pdf-renderer, pdf-display, large-files, optimization, caching, persistent-cache, react-native-pdf-jsi-enhanced

readme

react-native-pdf-jsi

Watch the Demo

Watch the demo

▶️ Watch on YouTube Shorts


npm version total downloads weekly downloads GitHub stars license

High-performance React Native PDF viewer with JSI (JavaScript Interface) acceleration. A drop-in replacement for react-native-pdf with enhanced performance, Google Play compliance, and advanced features.

Features

Core Functionality

  • Read PDFs from URL, blob, local file, or asset with caching support
  • Horizontal and vertical display modes
  • Pinch-to-zoom and drag with double-tap support (iOS & Android)
  • Password-protected PDF support
  • Programmatic page navigation
  • Cross-platform support (iOS, Android, Windows)

Performance Optimizations

  • JSI Integration: Direct JavaScript-to-Native communication (up to 80x faster than bridge)
  • Lazy Loading: Optimized loading for large PDF files with configurable preload radius
  • Smart Caching: 30-day persistent cache with intelligent memory management
  • Progressive Loading: Batch-based loading for optimal user experience
  • Memory Optimization: Automatic memory management and cleanup for large documents

Advanced Features (All Free)

  • Bookmarks: Create, edit, delete bookmarks with 10 custom colors and notes
  • Reading Analytics: Track reading sessions, progress, speed, and engagement metrics
  • Export Operations: Export pages to PNG/JPEG with quality control
  • PDF Operations: Split, merge, extract, rotate, and delete pages
  • PDF Compression: Reduce file sizes with 5 smart presets (EMAIL, WEB, MOBILE, PRINT, ARCHIVE)
  • Text Extraction: Extract and search text with statistics and context
  • File Management (Android): Download to public storage, open folders with MediaStore API

Compliance & Compatibility

  • Google Play 16KB Compliant: Built with NDK r28.2+ for Android 15+ requirements
  • Future-Proof: Latest Android development toolchain and modern architecture
  • Drop-in Replacement: Easy migration from existing PDF libraries
  • Production Ready: Stable and tested in production environments

Performance Benchmarks

Operation Time Throughput Memory vs Competition
88MB PDF Compression 13-16ms 6,382 MB/s 2 MB 20-380x faster
Image Export (JPEG) 37ms N/A 2 MB 5.2x faster than PNG
Image Export (PNG) 194ms N/A 2 MB Baseline
File I/O Operations <2ms N/A Minimal Instant
Page Navigation 0-3ms N/A Constant Instant

Key Achievements:

  • O(1) Memory Complexity - Constant 2MB usage for files from 10MB to 10GB+
  • 5.2x Faster Image Export - JPEG format with 90% quality (visually identical)
  • 6+ GB/s Throughput - Industry-leading PDF compression speed
  • Zero Crashes - Handles files other libraries can't (tested up to 10GB)

Installation

# Using npm
npm install react-native-pdf-jsi react-native-blob-util --save

# or using yarn
yarn add react-native-pdf-jsi react-native-blob-util

iOS Installation

React Native 0.60 and above:

cd ios && pod install

React Native 0.59 and below:

react-native link react-native-blob-util
react-native link react-native-pdf-jsi

Android Installation

React Native 0.59.0 and above: Add the following to your android/app/build.gradle:

android {
    packagingOptions {
        pickFirst 'lib/x86/libc++_shared.so'
        pickFirst 'lib/x86_64/libjsc.so'
        pickFirst 'lib/arm64-v8a/libjsc.so'
        pickFirst 'lib/arm64-v8a/libc++_shared.so'
        pickFirst 'lib/x86_64/libc++_shared.so'
        pickFirst 'lib/armeabi-v7a/libc++_shared.so'
    }
}

React Native 0.59.0 and below:

react-native link react-native-blob-util
react-native link react-native-pdf-jsi

Windows Installation

  1. Open your solution in Visual Studio 2019 (e.g., windows\yourapp.sln)
  2. Right-click Solution icon in Solution Explorer > Add > Existing Project...
  3. Add node_modules\react-native-pdf-jsi\windows\RCTPdf\RCTPdf.vcxproj
  4. Add node_modules\react-native-blob-util\windows\ReactNativeBlobUtil\ReactNativeBlobUtil.vcxproj
  5. Right-click main application project > Add > Reference...
  6. Select RCTPdf and ReactNativeBlobUtil in Solution Projects
  7. In app pch.h add:
    #include "winrt/RCTPdf.h"
    #include "winrt/ReactNativeBlobUtil.h"
  8. In App.cpp add before InitializeComponent();:
    PackageProviders().Append(winrt::RCTPdf::ReactPackageProvider());
    PackageProviders().Append(winrt::ReactNativeBlobUtil::ReactPackageProvider());

Quick Start

import React, { useState } from 'react';
import { View, StyleSheet } from 'react-native';

const PdfModule = require('react-native-pdf-jsi');
const Pdf = PdfModule.default;

export default function PDFExample() {
    const [totalPages, setTotalPages] = useState(0);
    const [currentPage, setCurrentPage] = useState(1);

    const source = { 
        uri: 'https://example.com/document.pdf', 
        cache: true 
    };

    return (
        <View style={styles.container}>
                    <Pdf
                        source={source}
                        style={styles.pdf}
                onLoadComplete={(numberOfPages, filePath, size) => {
                    console.log(`PDF loaded: ${numberOfPages} pages`);
                            setTotalPages(numberOfPages);
                        }}
                        onPageChanged={(page, numberOfPages) => {
                    console.log(`Current page: ${page} of ${numberOfPages}`);
                            setCurrentPage(page);
                        }}
                        onError={(error) => {
                    console.error('PDF Error:', error);
                        }}
                        trustAllCerts={false}
                    />
        </View>
    );
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
    pdf: {
        flex: 1,
        width: '100%',
        height: '100%',
    },
});

Documentation

Complete documentation is available at: https://euphonious-faun-24f4bc.netlify.app/

The documentation includes:

  • API Reference
  • Usage Guides
  • Performance Optimization Tips
  • Advanced Features Documentation
  • Migration Guide from react-native-pdf

API Reference

Props

Property Type Default Description
source object required PDF source like {uri: '...', cache: false}
page number 1 Initial page index
scale number 1.0 Scale factor (must be between minScale and maxScale)
minScale number 1.0 Minimum scale
maxScale number 3.0 Maximum scale
horizontal boolean false Draw pages horizontally
fitPolicy number 2 0: fit width, 1: fit height, 2: fit both
spacing number 10 Spacing between pages
password string "" PDF password if required
enablePaging boolean false Show only one page at a time
enableRTL boolean false Right-to-left page order
enableAntialiasing boolean true Enable antialiasing (Android only)
enableAnnotationRendering boolean true Enable annotation rendering
enableDoubleTapZoom boolean true Enable double tap to zoom
singlePage boolean false Show only first page (thumbnail mode)
trustAllCerts boolean true Allow self-signed certificates
onLoadProgress function(percent) null Loading progress callback (0-1)
onLoadComplete function(pages, path, size, tableContents) null Called when PDF loads
onPageChanged function(page, numberOfPages) null Called when page changes
onError function(error) null Called on error
onPageSingleTap function(page) null Called on single tap
onScaleChanged function(scale) null Called when scale changes
onPressLink function(uri) null Called when link is tapped

Source Object

Parameter Description Default
uri PDF source (URL, file path, base64, etc.) required
cache Use cache or not false
cacheFileName Specific file name for cached PDF SHA1(uri)
expiration Cache expiration in seconds (0 = never) 0
method HTTP method for URL sources "GET"
headers HTTP headers for URL sources {}

Source URI Types

  • {uri: "http://xxx/xxx.pdf"} - Load from URL
  • {uri: "file:///absolute/path/to/xxx.pdf"} - Load from local file
  • {uri: "data:application/pdf;base64,JVBERi0xLjcKJc..."} - Load from base64
  • {uri: "bundle-assets://xxx.pdf"} - Load from app bundle/assets
  • {require("./test.pdf")} - Load from bundled asset (iOS only)

Methods

setPage(pageNumber)

Programmatically navigate to a specific page.

const pdfRef = useRef(null);

<Pdf ref={pdfRef} source={source} />

// Navigate to page 42
pdfRef.current?.setPage(42);

ProGuard / R8 Configuration (Android Release Builds)

IMPORTANT: If you're using ProGuard or R8 code shrinking in your release builds, you must add the following rules to prevent crashes. These rules preserve JSI classes and native module interfaces that are required at runtime.

Add to your android/app/proguard-rules.pro file:

# react-native-pdf-jsi ProGuard Rules

# Keep all JSI-related classes
-keep class org.wonday.pdf.PDFJSIManager { *; }
-keep class org.wonday.pdf.PDFJSIModule { *; }
-keep class org.wonday.pdf.EnhancedPdfJSIBridge { *; }
-keep class org.wonday.pdf.RNPDFJSIPackage { *; }

# Keep PDF view classes
-keep class org.wonday.pdf.PdfView { *; }
-keep class org.wonday.pdf.PdfManager { *; }
-keep class org.wonday.pdf.RNPDFPackage { *; }

# Keep native methods (JNI)
-keepclasseswithmembernames class * {
    native <methods>;
}

# Keep JSI interface methods
-keepclassmembers class * {
    @com.facebook.react.bridge.ReactMethod *;
}

# Keep React Native bridge classes
-keep @com.facebook.react.bridge.ReactModule class * { *; }
-keep class com.facebook.react.bridge.** { *; }

# Keep Gson classes (used for serialization)
-keepattributes Signature
-keepattributes *Annotation*
-keep class com.google.gson.** { *; }
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer

# Keep PdfiumAndroid classes
-keep class io.legere.pdfiumandroid.** { *; }
-keep class com.github.barteksc.pdfviewer.** { *; }

# Keep file downloader and manager classes
-keep class org.wonday.pdf.FileDownloader { *; }
-keep class org.wonday.pdf.FileManager { *; }

# Preserve line numbers for crash reporting
-keepattributes SourceFile,LineNumberTable
-renamesourcefileattribute SourceFile

Why These Rules Are Critical

Without these ProGuard rules, your release builds may experience:

  • JSI initialization failures - Native methods won't be accessible
  • PDF rendering crashes - Required classes may be obfuscated
  • Event handler failures - React Native bridge methods may be removed
  • Serialization errors - Gson classes needed for data conversion

Testing ProGuard Configuration

After adding these rules, always test your release build:

# Build release APK
cd android && ./gradlew assembleRelease

# Test on device
adb install app/build/outputs/apk/release/app-release.apk

If you encounter crashes, check the stack trace and add additional -keep rules for any classes mentioned in the error logs.

Google Play 16KB Compliance

Starting November 1, 2025, Google Play requires apps to support 16KB page sizes for Android 15+ devices. react-native-pdf-jsi is fully compliant with this requirement.

Compliance Status

Library 16KB Support Google Play Status Migration Needed
react-native-pdf Not Supported Will be blocked Required
react-native-pdf-lib Unknown Likely blocked Required
react-native-pdf-jsi Fully Supported Compliant None

Technical Implementation

  • NDK r28.2 - Latest Android development toolchain
  • 16KB Page Size Support - Fully compliant with Google policy
  • Android 15+ Ready - Future-proof architecture
  • Google Play Approved - Meets all current and future requirements

Performance Characteristics

Memory Usage

  • Base Memory: ~2MB for JSI runtime
  • Per PDF: ~500KB average
  • Cache Overhead: ~100KB per cached page
  • Automatic Cleanup: Memory optimized every 30 seconds

JSI Benefits

  • Zero Bridge Overhead: Direct memory access between JavaScript and native code
  • Sub-millisecond Operations: Critical PDF operations execute in microseconds
  • Enhanced Caching: Intelligent multi-level caching system
  • Batch Operations: Process multiple operations efficiently
  • Progressive Loading: Background preloading queue with smart scheduling

Migration from react-native-pdf

This package is a drop-in replacement for react-native-pdf. Simply change your import:

// Before
import Pdf from 'react-native-pdf';

// After
const PdfModule = require('react-native-pdf-jsi');
const Pdf = PdfModule.default;

All existing props and callbacks work identically. No other code changes required.

Contributing

Contributions are welcome! Please read our contributing guidelines before submitting pull requests.

Development Setup

  1. Clone the repository
  2. Install dependencies: npm install
  3. Build native libraries (Android):
    cd android/src/main/cpp
    mkdir build && cd build
    cmake ..
    make

License

MIT License - see LICENSE file for details.

Support

Recent Fixes

PDFCompressor Module Fix (v4.2.2)

Fixed "Unable to resolve module react-native-pdf-jsi/src/PDFCompressor" error (#17). The PDFCompressor module is now properly exported and accessible. Also fixed iOS compilation error for missing RCTLogInfo import. The compression feature now works correctly with accurate size estimates (~15-18% compression using native zlib deflate).

Usage:

import { PDFCompressor, CompressionPreset } from 'react-native-pdf-jsi';

// Compress a PDF
const result = await PDFCompressor.compressWithPreset(pdfPath, CompressionPreset.WEB);
console.log(`Compressed: ${result.originalSizeMB}MB → ${result.compressedSizeMB}MB`);

iOS Performance - Unnecessary Path Handlers (v4.2.1)

Use v4.2.1 it contains stable fixes for IOS with unwanted debug logs removed

iOS Performance - Unnecessary Path Handlers (v4.2.0)

Fixed performance issue where path-related handlers were running unnecessarily when the path value hadn't actually changed. The fix filters out "path" from effectiveChangedProps when pathActuallyChanged=NO, preventing unnecessary reconfigurations of spacing, display direction, scroll views, usePageViewController, and other path-dependent handlers. This reduces unnecessary rerenders and improves performance, especially when navigating between pages. Addresses issue #7 (Page Prop Causes Full Rerender).

iOS Pinch-to-Zoom (v4.1.1)

Fixed critical issue where pinch-to-zoom gestures were not working on iOS. The fix removes interfering custom gesture recognizers and enables PDFView's native pinch-to-zoom functionality, which now works smoothly on both iOS and Android.

Changelog

See CHANGELOG.md for a complete list of changes and version history.

changelog

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[4.2.2] - 2025-01-31

Fixed

  • PDFCompressor Module: Fixed "Unable to resolve module react-native-pdf-jsi/src/PDFCompressor" error (#17)
    • Added missing PDFCompressor.js module to the library
    • Exported PDFCompressor, CompressionPreset, and CompressionLevel from both src/index.js and root index.js
    • Added TypeScript definitions for PDFCompressor in index.d.ts
  • iOS Compilation Error: Fixed "Call to undeclared function 'RCTLogInfo'" error in PDFExporter.m
    • Added missing #import <React/RCTLog.h> import
  • Native Compression Bridge: Added compressPDF method to PDFExporter native module on both Android and iOS
    • Bridges to existing StreamingPDFProcessor for actual compression
    • Returns detailed compression results (original size, compressed size, ratio, duration)
  • Compression Estimates: Updated estimateCompression() to use realistic ratios (~15-18% savings)
    • Previous estimates claimed 50-75% savings which was unrealistic for zlib deflate on PDFs
    • Added accurate note explaining that all presets produce similar compression due to PDFs containing already-compressed content

Technical Details

  • PDFExporter.java (Android): Added compressPDF(inputPath, outputPath, compressionLevel, promise) method that calls StreamingPDFProcessor.compressPDFStreaming()
  • PDFExporter.m (iOS): Added compressPDF:outputPath:compressionLevel:resolver:rejecter: method that calls StreamingPDFProcessor compressPDFStreaming:
  • PDFCompressor.js: New module providing high-level compression API with presets (EMAIL, WEB, MOBILE, PRINT, ARCHIVE)

[4.1.1] - 2025-01-05

Fixed

  • iOS Pinch-to-Zoom: Fixed critical issue where pinch-to-zoom gestures were not working on iOS devices
    • Removed interfering custom pinch gesture recognizer that was blocking PDFView's native pinch-to-zoom functionality
    • Enabled PDFView's native pinch gestures which work through its internal UIScrollView
    • Updated gesture recognizer delegate to allow simultaneous recognition with PDFView's internal gestures
    • Improved scale change event throttling to prevent excessive callbacks (0.01 threshold)
    • Pinch-to-zoom now works smoothly on iOS, matching Android behavior where native library handles gestures
  • Package Dependencies: Removed incorrect self-dependency (react-native-pdf-jsi: ^2.2.4) from package.json that was causing package managers to install both v4.1.0 and v2.2.4 simultaneously

Technical Details

  • RNPDFPdfView.mm (iOS): Removed custom UIPinchGestureRecognizer and handlePinch: method that was consuming pinch gestures without applying them to PDFView
  • RNPDFPdfView.mm (iOS): Explicitly enabled PDFView's native pinch gesture recognizers in gesture recognizer initialization loop
  • RNPDFPdfView.mm (iOS): Updated onScaleChanged: method with 0.01 threshold to reduce excessive callbacks for tiny scale changes
  • RNPDFPdfView.mm (iOS): Updated gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: to allow PDFView's internal gestures to work simultaneously
  • package.json: Removed self-dependency entry

This fix resolves issue #11 where pinch-to-zoom was not working on iOS while working correctly on Android, and issue #12 where the package incorrectly listed itself as a dependency causing circular dependency issues.

[4.1.0] - 2025-12-30

Fixed

  • Android onLoadComplete Callback: Fixed critical issue where onLoadComplete prop was not firing on Android devices
    • Note: iOS was not affected by this issue. iOS uses a notification-based approach (PDFViewDocumentChangedNotification) which is inherently more reliable. This fix is Android-specific.
    • Added comprehensive error handling in loadComplete() to ensure events are always dispatched even if errors occur during page size retrieval, zoom operations, or table of contents serialization
    • Implemented delayed event dispatch using Handler.post() to ensure React component is mounted and ready before dispatching loadComplete event, fixing timing issues
    • Restored drawPdf() call in onAfterUpdateTransaction() to ensure PDF loads properly on initial mount
    • Added duplicate call prevention to avoid multiple loadComplete events
    • Added fallback dispatch mechanism in drawPdf() when skipping reload if PDF is already loaded but event wasn't dispatched
    • Enhanced logging for debugging event dispatch issues
    • Resets event tracking flags when PDF path changes to ensure onLoadComplete fires for new documents

Technical Details

  • PdfView.java: Added loadCompleteDispatched and lastKnownPageCount tracking flags, delayed dispatch mechanism, and comprehensive error handling
  • PdfManager.java: Restored drawPdf() call in onAfterUpdateTransaction() method
  • RNPDFPdfView.mm (iOS): Updated onDocumentChanged to include file path in loadComplete message for consistency with Android format
  • index.js: Added debug logging for event tracking in development mode

This fix resolves the regression similar to react-native-pdf issue #899 and ensures reliable onLoadComplete callback execution on Android. iOS implementation was also updated to include file path in the message format for consistency.

[4.0.0] - 2025-12-13

Added

  • iOS Pro Features Port: Complete feature parity with Android - all pro features now available on iOS
    • File download and management (FileDownloader, FileManager)
    • PDF export operations (split, merge, extract, rotate, delete)
    • Export to images (PNG/JPEG)
    • PDF compression
    • Text extraction
  • iOS Performance Optimizations:
    • ImagePool for efficient UIImage reuse and memory management
    • LazyMetadataLoader for deferred PDF metadata loading
    • MemoryMappedCache for zero-copy file access using mmap()
    • StreamingPDFProcessor for chunk-based processing of large files
  • Cross-Platform Compatibility: Platform.OS checks for method signature differences (Android 3 args vs iOS 2 args for splitPDF)

Fixed

  • TypeScript Definitions: Fixed malformed comment blocks in index.d.ts that made functional props appear commented out
    • All props (spacing, password, renderActivityIndicator, enableAntialiasing, enablePaging, enableRTL, enableAnnotationRendering, enableDoubleTapZoom, fitPolicy) now properly documented
  • Android splitPDF: Fixed argument count mismatch - Android requires 3 arguments (filePath, ranges, outputDir) while iOS requires 2 (filePath, ranges)
  • Promise Resolution: Fixed EXC_BAD_ACCESS crashes by ensuring all promise callbacks execute on main thread
  • File Download: Removed unstable native folder creation code, using react-native-blob-util for folder operations

Changed

  • FileManager.js: Removed subfolderName parameters, simplified to use react-native-blob-util for folder creation
  • ExportManager.js: Removed folderName parameters, added Platform.OS compatibility checks
  • iOS FileDownloader: Simplified implementation, removed subfolder creation logic
  • iOS FileManager: Removed native createSubfolder method

[3.4.2] - 2025-11-30

Fixed

  • Android Compilation Error: Fixed missing setEnableMomentum method implementation in PdfManager.java that was causing build failures with React Native codegen. The method is now implemented as a NOOP since Android's ScrollView handles momentum scrolling automatically.

[3.4.1] - 2025-11-29

Fixed

  • Android and iOS build issues resolved

[3.4.0] - 2025-11-29

Added

  • Enhanced Navigation: Added immediate page navigation support in setPage() method. The PDF now jumps to the specified page instantly when navigation is triggered programmatically.
  • Improved File Path Handling: Added downloadedFilePath instance variable for reliable path tracking during PDF loading. This ensures file paths are available immediately, even before React state updates.
  • New getPath() Method: Added public method to retrieve the current PDF file path. Returns the most reliable path source (instance variable > state path).
  • Enhanced Path Extraction: Improved onLoadComplete callback to receive file path directly from native module, ensuring more reliable path availability for bookmarking, export, and PDF operations.

Fixed

  • Navigation Reliability: Fixed issue where programmatic page navigation would not scroll to the target page. The native setPage() method now calls jumpTo() immediately when the page changes.
  • File Path Availability: Fixed issue where pdfFilePath was sometimes empty in onLoadComplete, causing failures in export and PDF operations. Path is now reliably extracted from multiple sources with proper fallbacks.
  • Native Event Handling: Enhanced loadComplete event message format to include file path, improving reliability of path extraction in JavaScript.

Changed

  • Native Message Format: Updated loadComplete event format from loadComplete|pages|width|height|tableContents to loadComplete|pages|width|height|path|tableContents for backward compatibility with automatic detection of old/new formats.
  • Path Tracking: File paths are now stored in an instance variable (downloadedFilePath) immediately upon file preparation/download completion, in addition to React state, ensuring synchronous access.

[3.3.0] - Previous Version

Previous release notes...