Как реализовать кэширование изображений?
В React Native кэширование изображений — это важная практика для оптимизации производительности, ускорения загрузки и уменьшения количества сетевых запросов. Особенно это актуально при отображении изображений из сети (например, с CDN или API), когда одни и те же изображения повторяются в списках или на разных экранах.
Базовый Image компонент из react-native не поддерживает кэширование на Android, а на iOS — только частично, что делает его непригодным для серьёзного использования в продуктивных проектах.
Стандартный Image и его ограничения
import { Image } from 'react-native';
<Image
source={{ uri: 'https://example.com/image.jpg' }}
style={{ width: 100, height: 100 }}
/>
Проблемы:
-
На Android изображения всегда загружаются заново
-
На iOS они кэшируются системой, но не управляемо
-
Нет контроля над стратегиями кэширования, размером, приоритетом загрузки
-
Нет прогресс-индикатора
Лучшее решение — react-native-fast-image
react-native-fast-image — это высокопроизводительный компонент-замена для Image, основанный на нативных библиотеках:
-
iOS: SDWebImage
-
Android: Glide
Библиотека поддерживает:
-
Кэширование (memory + disk)
-
Приоритеты загрузки
-
Прогресс и обработку ошибок
-
Использование HTTP-заголовков
-
Resize modes, как в стандартном Image
Установка react-native-fast-image
npm install react-native-fast-image
Для bare React Native (не Expo) может потребоваться npx pod-install для iOS и gradlew clean на Android.
Expo не поддерживает FastImage из коробки. Использование возможно через Expo Dev Client с prebuild.
Пример использования
import FastImage from 'react-native-fast-image';
<FastImage
style={{ width: 100, height: 100 }}
source={{
uri: 'https://example.com/image.jpg',
priority: FastImage.priority.normal,
cache: FastImage.cacheControl.immutable, // или web, cacheOnly
}}
resizeMode={FastImage.resizeMode.cover}
/>
Настройки cacheControl
FastImage.cacheControl управляет стратегией кэширования:
-
immutable — кэширует изображение навсегда (лучший вариант для CDN)
-
web — соблюдает HTTP cache headers (как браузер)
-
cacheOnly — загружает только из кэша, не делает сетевой запрос
Обработка ошибок и индикаторы
<FastImage
style={{ width: 200, height: 200 }}
source={{ uri: 'https://example.com/image.jpg' }}
onLoadStart={() => console.log('Загрузка началась')}
onProgress={e => console.log('Прогресс', e.nativeEvent.loaded / e.nativeEvent.total)}
onLoad={() => console.log('Загрузка завершена')}
onError={() => console.log('Ошибка загрузки')}
/>
Работа с FlatList и FastImage
FastImage особенно полезен при отображении списка изображений, т.к. предотвращает повторную загрузку и визуальные глитчи:
<FlatList
data={images}
renderItem={({ item }) => (
<FastImage
style={{ width: 100, height: 100 }}
source={{ uri: item.url, priority: FastImage.priority.high }}
/>
)}
keyExtractor={item => item.id}
/>
Продвинутые стратегии кэширования
- **Предзагрузка изображений:
**
FastImage.preload(\[
{ uri: 'https://example.com/image1.jpg' },
{ uri: 'https://example.com/image2.jpg' },
\]);
Это загружает изображения в кэш до их использования, полезно для splash-экранов или прелоадинга ассетов.
- **Очистка кэша вручную:
**
FastImage.clearMemoryCache();
FastImage.clearDiskCache();
Полезно при логине нового пользователя или очистке временных данных.
- **Использование HTTP-заголовков:
**
source={{
uri: 'https://example.com/secure-image.jpg',
headers: {
Authorization: 'Bearer token',
},
cache: FastImage.cacheControl.web,
}}
Это даёт возможность работать с изображениями, требующими авторизации.
Альтернативы для Expo
Так как react-native-fast-image не работает в Expo Go, доступны другие варианты:
- expo-image (с SDK 48+) — экспериментальный компонент от Expo:
import { Image } from 'expo-image';
<Image
source="https://example.com/image.jpg"
contentFit="cover"
style={{ width: 100, height: 100 }}
/>
Поддерживает:
-
Кэширование на диске
-
Async load
-
Progressive rendering
-
**Кэширование вручную через FileSystem:
**
import \* as FileSystem from 'expo-file-system';
const localUri = \`${FileSystem.cacheDirectory}image.jpg\`;
const download = await FileSystem.downloadAsync(
'https://example.com/image.jpg',
localUri
);
После загрузки можно использовать Image с uri: download.uri.
Общие советы
-
Всегда указывай фиксированные размеры изображений (width и height) для предотвращения лишних перерасчётов layout
-
Используй resizeMode='cover' или contain в зависимости от макета
-
Старайся использовать CDN с правильными заголовками cache-control для web стратегии
-
Предзагружай изображения на экранах, где они появятся позже
-
Храни аватары и часто используемые изображения на устройстве или в кэше, чтобы сократить повторные запросы
Кэширование изображений в React Native — ключевой шаг к созданию отзывчивых, плавных и экономных по трафику мобильных приложений. Использование FastImage или expo-image позволяет добиться профессионального UX без лишней нагрузки на сеть и память устройства.