0

I am using expo Image to cache and prefetch images in my react native app It works perfectly on android but it is extremely slow on IOS For the purpose of debugging I added many logs to this get the idea here is my code

import { Image } from "expo-image";
import { useEffect, useState } from "react";
import { assetUrls } from "../Constants/assetConstants";
import { Platform } from "react-native";

export const usePreloadImages = () => {
  const [loaded, setLoaded] = useState<boolean>(false);
  useEffect(() => {
    let cancelled = false;
    const preload = async () => {
      console.log("preloading mate");
      const start = Date.now();
      try {
        const results = await Promise.all(
          assetUrls.map(async (url) => {
            console.log("⏳ Prefetching:", url);
            try {
              await Image.prefetch(url);
              console.log("✅ Prefetched:", url);
            } catch (err) {
              console.log("❌ Prefetch failed:", url, err);
            }
          })
        );
        const end = Date.now();
        console.log("end at:", end);
        console.log(`✅ Prefetch complete! Time taken: ${end - start} ms`);
        console.log("Prefetch complete verifying cache");
        // await debugImageCache(assetUrls);
        if (!cancelled) setLoaded(true);
      } catch (err) {
        console.error("💥 Error in prefetch loop:", err);
        if (!cancelled) setLoaded(true);
      }
    };
    preload();
    return () => {
      cancelled = true;
    };
  }, []);
  return loaded;
};

and on comparing times I got this

Android Prefetch complete! Time taken: 2052 ms

ios Prefetch complete! Time taken: 31636 ms

so why is the same code taking almost 150% more time and what to do to solve this

1 Answer 1

0

I figured out that it was a problem related to SDWebImage which expo image uses so used alternate library for IOS which used nuke named react-native-turbo-image. You can use any other library you want

export const usePreloadImagesHybrid = () => {
  const [loaded, setLoaded] = useState<boolean>(false);

  useEffect(() => {
    let cancelled = false;
    const preload = async () => {
      // console.log("🟢 Starting image preloading...");

      const start = Date.now();

      try {
        if (Platform.OS === "android") {
          // Expo Image prefetch + cache debug
          for (const url of assetUrls) {
            // console.log("⏳ Prefetching (Expo):", url);
            try {
              await Image.prefetch(url);
              // const cachePath = await Image.getCachePathAsync(url);
              // console.log(`✅ Prefetched: ${url}\nCache path: ${cachePath}`);
            } catch (err) {
              console.log("❌ Prefetch failed:", url, err);
            }
          }
        } else if (Platform.OS === "ios") {
          // TurboImage prefetch only
          for (const url of assetUrls) {
            // console.log("⏳ Prefetching (TurboImage):", url);
            try {
              await TurboImage.prefetch([{ uri: url }]);
              // console.log("✅ Prefetched:", url);
            } catch (err) {
              console.log("❌ Prefetch failed:", url, err);
            }
          }
        }
        const end = Date.now();
        console.log(`🕒 Prefetch complete! Time taken: ${end - start} ms`);
        if (!cancelled) setLoaded(true);
      } catch (err) {
        console.error("💥 Error during prefetch:", err);
        if (!cancelled) setLoaded(true);
      }
    };

    preload();

    return () => {
      cancelled = true;
    };
  }, []);

  return loaded;
};
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.