ArchiveExpo SnackDiscord and ForumsNewsletter


Learn about using local and remote assets.

Images, fonts, videos, sounds, and any other file that your app depends on that is not JavaScript are considered to be an asset.

Local assets

Assets stored on your file system can be imported like JavaScript modules, using require or import. For example, from App.js, to render an image called example.png that is stored within the project's assets/images directory you can use require to import the image and then pass it to the Image component:

<Image source={require('./assets/images/example.png')} />

The bundler will automatically provide a width and height for images imported this way. For more information, see Static Image Resources.

Libraries like expo-av and expo-file-system work similar to Image with local assets.

Local assets this way will be served over HTTP in development, and they will be automatically bundled into your app binary at build time.

When you publish an update to your app with EAS Update, your assets will be uploaded and served from a CDN. Any asset that is not already included in the build that receives the update will be downloaded before launching the update. When testing an app in Expo Go, assets will be downloaded as the project is running. You can load these before your app starts with the useAssets hook.

Remote assets

To render a remote image, pass the URL to the image to the Image component:

<Image source={{ uri: 'https://example.com/logo.png' }} />

No guarantee can be made about the availability of the images that you refer to with a web URL because an internet connection may not be available or the asset may have been removed. Additionally, we don't have the same amount of information about arbitrary web URLs: when your assets are available on the local filesystem, the bundler can read some metadata (for example, width and height) and pass that through to your app, so you don't need to specify a width and height. When specifying a remote web URL, you will need to explicitly specify a width and height, or it will default to 0x0. Lastly, as you will see later, caching behavior is different in both cases.

Libraries like expo-av and expo-file-system work similar to Image with local assets.

Remote assets are not bundled into binaries at build time. They are also not considered part of an EAS Update bundle.

Customizing supported asset extensions

If you need to import a file type that is not recognized by Metro by default, you can modify the Metro configuration. For example, you may want to use the .db to import a database into your app. Read more about how to customize the asset extensions supported by Metro for Android and iOS in Customizing Metro.



You can compress images using tools such as guetzli, pngcrush, or optipng. imagemin is another program and JS library that supports plugins for various optimizers. Many online services can optimize your images for you.

Some image optimizers are lossless. This means they re-encode your image to be smaller without any change, or loss, in the pixels that are displayed. When you need each pixel to be untouched from the original image, a lossless optimizer and a lossless image format like PNG is a good choices.

Other image optimizers are lossy, which means the optimized image is different than the original image. Often, lossy optimizers are more efficient because they discard visual information that reduces file size while making the image look nearly the same to humans. Tools like imagemagick can use comparison algorithms like SSIM to give a sense of how similar two images look. It's quite common for an optimized image that is over 95% similar to the original image to be far less than 95% of the original file size!


As explained above, in production builds, your local assets will all be bundled and loaded from disk rather than over the network as expected for native apps, but they must be loaded over the network when previewing in development builds. On the web, the font loading problem is known by: Flash of Unstyled Text (FOUT), Flash of Invisible Text (FOIT), and Flash of Faux Text (FOFT).

The default behavior with @expo/vector-icons icons is a FOIT on the first load, and on subsequent loads, the font will be automatically cached. You may want to preload fonts during the initial loading screen with useFonts. For example:

useFonts([require('./assets/fonts/ComicSans.ttf', FontAwesome.font)]);