Ми часто стикаємося з ситуацією, коли просте завдання — показати PDF — перетворюється на головний біль. 200-сторінковий документ на iPhone SE призводить до смиканого скролу та неконтрольованого зростання пам'яті до 500 МБ з наступним SIGKILL від iOS. Проблема в рендерингу: кожна сторінка PDF — це векторний документ, який потрібно растерувати під конкретний масштаб та роздільність екрану. Наша команда, маючи 5-річний досвід у мобільній розробці та реалізувавши понад 30 проєктів з інтеграцією PDF-в'юверів, вирішила це завдання для кількох замовників. Один із клієнтів — великий агрегатор документації — зіткнувся з падінням додатку на Android при відкритті 150-сторінкового PDF. Ми впровадили посторінкове завантаження на основі PdfRenderer, що знизило пікове споживання пам'яті на 60% та усунуло краші. Середня економія часу розробки при використанні готових модулів становить 3–4 тижні, а вартість інтеграції базового рішення визначається після аналізу завдання.
Чому нативний рендеринг кращий за WebView?
<WebView source={{ uri: 'file://...' }} — найшвидший спосіб показати PDF. iOS WebKit рендерить PDF нативно. Однак немає контролю над UI (не додати custom toolbar, анотації, пошук), і PDF відкривається цілком у пам'ять. На 50+ сторінках — ризик OOM. Нативний рендеринг через PDFKit (iOS) та PdfRenderer (Android) дає повний контроль, але вимагає нативних модулів у React Native. Ми зазвичай обираємо золоту середину — react-native-pdf.
Порівняння підходів до вбудовування PDF-в'ювера
| Підхід | Продуктивність | Контроль UI | Час розробки |
|---|---|---|---|
| WebView | Середня (ризик на великих PDF) | Низький | 1–2 дні |
| Нативний модуль (PDFKit/PdfRenderer) | Висока | Повний | 1–2 тижні |
| react-native-pdf | Висока | Частковий (через пропси) | 3–5 днів |
| Flutter SfPdfViewer | Висока | Повний (через Flutter API) | 3–5 днів |
react-native-pdf: готове рішення
react-native-pdf — React Native обгортка над нативними PDF API обох платформ. Під капотом: PDFKit на iOS, PdfRenderer на Android. Посторінковий рендеринг — у пам'яті лише видимі сторінки + 1–2 буферні.
import Pdf from 'react-native-pdf'; const PDFViewer = ({ uri }: { uri: string }) => { const [totalPages, setTotalPages] = useState(0); const [currentPage, setCurrentPage] = useState(1); return ( <Pdf source={{ uri, cache: true }} onLoadComplete={(numberOfPages) => setTotalPages(numberOfPages)} onPageChanged={(page) => setCurrentPage(page)} onError={(error) => console.error(error)} style={{ flex: 1 }} enablePaging horizontal fitPolicy={0} scale={1.0} minScale={0.5} maxScale={3.0} /> ); }; Параметр cache: true — перше завантаження зберігає файл у директорію кешу додатку. Повторне відкриття не робить HTTP-запит, що прискорює відображення до 3 разів на файлах 10+ МБ. Важливо: кеш не керується автоматично, потрібне очищення за TTL або розміром.
Як реалізувати ліниве завантаження сторінок?
При відкритті PDF з URL бібліотека завантажує весь файл перед рендерингом. 50 МБ PDF — користувач чекає 8–12 секунд. Оптимальне рішення — HTTP Range запити, якщо сервер підтримує Accept-Ranges: bytes. Нативна реалізація для iOS через PDFDocument(url:) з URLSession підтримує прогресивний рендеринг (Apple PDFKit Documentation). Для React Native розроблено custom native module, який використовує PDFDocument з CGPDFDataProvider для потокового завантаження. Для більшості проєктів простіше: показуємо першу сторінку як placeholder (thumbnail, попередньо згенерований на сервері через pdf2pic або ghostscript), поки завантажується повний файл. В одному з проєктів це скоротило час очікування з 8 до 1 секунди для PDF у 40 МБ.
Пошук по тексту та анотації
react-native-pdf підтримує пошук через pdfRef.current?.startSearch(query) — нативний пошук по тексту документа з підсвічуванням збігів. Анотації (виділення, нотатки, підписи) — окреме завдання. PSPDFKit — комерційний SDK з повним набором анотацій. Для open-source: PDFTron (Apryse) з free-тиром. У наших проєктах використовуємо PSPDFKit, якщо потрібно 10+ типів анотацій; у протилежному випадку — кастомний модуль на 2–3 типи (виділення, нотатка).
Як захистити PDF від несанкціонованого доступу?
PDF з паролем: react-native-pdf підтримує password prop. Корпоративні DRM-захищені PDF (Adobe AEPD, Microsoft IRM) потребують нативних бібліотек операторів — у RN не реалізовані напряму. У таких випадках ми рекомендуємо серверну роздачу з токеном авторизації. Приклад: підписаний URL з TTL 1 година.
Flutter: syncfusion_flutter_pdfviewer
Syncfusion надає SfPdfViewer — повнофункціональний PDF в'ювер для Flutter з посторінковим рендерингом, пошуком і виділенням. Community-ліцензія безкоштовна при доході до $1 млн/рік.
SfPdfViewer.network( 'https://cdn.example.com/document.pdf', onPageChanged: (PdfPageChangedDetails details) { setState(() => _currentPage = details.newPageNumber); }, ) Порівняння бібліотек для анотацій
| Бібліотека | Платформи | Вартість | Можливості |
|---|---|---|---|
| PSPDFKit | iOS, Android, Flutter, RN | Комерційна | Анотації, форми, підписи |
| Apryse (PDFTron) | iOS, Android, Flutter, RN | Безкоштовний тир + платні рівні | Анотації, редагування |
| Custom нативна | iOS/Android | Безкоштовно | Обмежений функціонал |
Що входить в роботу з інтеграції PDF-в'ювера
- Аналіз вимог: визначаємо платформу, обсяг документів, необхідні функції (пошук, анотації, захист).
- Вибір стеку: react-native-pdf, Flutter SfPdfViewer або нативний модуль.
- Налаштування рендерингу: посторінкове завантаження, кешування, підтримка масштабування.
- Реалізація UI: панель навігації, рядок пошуку, кнопки зуму.
- Інтеграція анотацій (опціонально): підключення PSPDFKit або Apryse.
- Оптимізація продуктивності: тестування на 5 пристроях з різними версіями ОС.
- Деплой та документація: передача вихідного коду, інструкція по збірці, API опис, 2 тижні підтримки після здачі.
Термін реалізації: базовий в'ювер для однієї платформи займає 2–3 тижні, крос-платформенне рішення з анотаціями — 4–6 тижнів. Якщо вам потрібно вбудувати PDF-в'ювер — зв'яжіться з нами, оцінимо проєкт за один день. Ми гарантуємо стабільність та продуктивність рішення. Отримайте консультацію — допоможемо обрати оптимальний підхід. Замовте впровадження — заощадьте час на розробку.







