ReactHustle

How to Load NextJS Images from an External URL

Jasser Mark Arioste

Jasser Mark Arioste

How to Load NextJS Images from an External URL

Hello, hustlers! In this tutorial, you'll learn how to load an image from an external URL in a NextJS project.

Introduction #

When loading images from an external URL, NextJS usually throws an error that a domain is not added in next.config.js. For example, if you're using the Image component in the following way:

import Image from "next/image"
// ...
  <Image
    src="https://placehold.co/600x400"
    alt="sample image"
    width={600}
    height={400}
  />
//...
123456789

You'll probably get some error of the sort in development:

Unhandled Runtime Error
Error: Invalid src prop (https://placehold.co/600x400) on `next/image`, hostname "placehold.co" is not configured under images in your `next.config.js`
See more info: https://nextjs.org/docs/messages/next-image-unconfigured-host
12

When loading images from an external URL, there are basically three options. First is adding the domain in next.config.js. Second, is using a custom image loader function in the Image component.  Lastly, you can use the unoptimized prop from the Image component.

Pre-requisites #

I assume you have basic knowledge of Nextjs.

The Recommended Way: Using images.domains property #

By default, NextJS recommends using the images.domains property inside next.config.js along with the Image component to easily load an image from an external URL.

For example, if you want to load an image from placehold.co, you may add it to the config file:

//next
/** @type {import('next').NextConfig} */
const nextConfig = {
    images: {
        domains: ["placehold.co"]
    }
}

module.exports = nextConfig
123456789

If you're deploying on Vercel, this will activate the caching and optimization mechanisms of NextJS, which retains the image URLs across each build to load the images faster for the average website visitor. This is an important thing to note because Vercel restricts the number of source URLs that you can cache. 1000 source URLs for the hobby plan, and 5000 source URLs for the pro plan.

You may not always want this feature. What if the images are already cached and optimized from the external URL? Using it this way is just redundant.

Using the unoptimized prop in Image #

The <Image/> component provides the unoptimized prop as another way to load images from an external URL. If the images are already optimized or there's no need for caching and optimization, you can use this property when rendering images. For example:

import Image from "next/image"
// ...
  <Image
    src="https://placehold.co/600x400"
    alt="sample image"
    unoptimized
    width={600}
    height={400}
  />
//...
12345678910

Since it's unoptimized, you don't have to add the domain in the images.domains property in next.config.js. This also won't increase your usage for Source URLs in Vercel. 

Using the loader prop in Image #

Besides the unoptimized prop, the Image component provides another way to load images from an external URL through the loader prop. The loader prop is a function that accepts an object which has the following properties: src, width, and quality. Using the loader property is useful if you use another Image API that processes the image. For example.

import Image from "next/image"
// ...
  <Image
      src="https://placehold.co/600x400"
      alt="sample image"
      loader={({ src, width, quality }) => {
        const url = new URL("https://myimageapi.co/optimize");
        url.searchParams.append("src", src);
        url.searchParams.append("w", width + "");
        url.searchParams.append("q", quality + "");
        return url.toString();
      }}
      width={600}
      height={400}
    />
// ...
12345678910111213141516

Since you are using a custom loader, you don't have to add the domain in the images.domains property in next.config.js. This also won't increase your usage for Source URLs in Vercel. 

Since it's a pain to add the loader prop every time you render an image, it's best to create a custom component for this. For example:

"use client";
import React from "react";
import Image, { ImageProps } from "next/image";
export type MyCustomImageProps = Omit<ImageProps, "loader">;

const MyCustomImage = (props: MyCustomImageProps) => {
  return (
    <Image
      {...props}
      alt={props.alt}
      loader={({ src, width, quality }) => {
        const url = new URL("https://myimageapi.co/optimize");
        url.searchParams.append("src", src);
        url.searchParams.append("w", width + "");
        url.searchParams.append("q", quality + "");
        return url.toString();
      }}
    />
  );
};

export default MyCustomImage;
12345678910111213141516171819202122

That's basically it!

Conclusion #

You learned three different ways of loading images from an external URL in NextJS. At this point, you have to decide which method best fits your needs and project requirements.

If you like this tutorial, please leave a like or share this article. For future tutorials like this, please subscribe to our newsletter or follow me on GitHub.

Resources #

Credits: Image by Nico Becker from Pixabay

Share this post!

Related Posts