Blitz is pivoting to framework agnostic toolkit. Click to learn more.
🚀Announcing Flightcontrol - Easily Deploy Blitz.js and Next.js to AWS 🚀
Back to Documentation Menu

Image Component and Image Optimization

Topics

Jump to a Topic

Blitz has a built-in Image Component and Automatic Image Optimization.

The Blitz Image Component, Image, is an extension of the HTML <img> element, evolved for the modern web.

The Automatic Image Optimization allows for resizing, optimizing, and serving images in modern formats like WebP when the browser supports it. This avoids shipping large images to devices with a smaller viewport. It also allows Blitz to automatically adopt future image formats and serve them to browsers that support those formats.

Automatic Image Optimization works with any image source. Even if the image is hosted by an external data source, like a CMS, it can still be optimized.

Instead of optimizing images at build time, Blitz optimizes images on-demand, as users request them. Unlike static site generators and static-only solutions, your build times aren't increased, whether shipping 10 images or 10 million images.

Images are lazy loaded by default. That means your page speed isn't penalized for images outside the viewport. Images load as they are scrolled into viewport.

Images are always rendered in such a way as to avoid Cumulative Layout Shift, a Core Web Vital that Google is going to use in search ranking.

Image Component

To add an image to your application, import the Image component:

import { Image } from "blitz"
import profilePic from "../public/me.png"

function Home() {
  return (
    <>
      <h1>My Homepage</h1>
      <Image src={profilePic} alt="Picture of the author" />
      <p>Welcome to my homepage!</p>
    </>
  )
}

export default Home

Image Imports

You can import images that live in your project. (Note that require is not supported—only import.)

With direct imports, width, height, and blurDataURL will be automatically provided to the image component. Alt text is still needed separately.

import { Image } from "blitz"
import profilePic from "../public/me.png"

function Home() {
  return (
    <>
      <h1>My Homepage</h1>
      <Image
        src={profilePic}
        alt="Picture of the author"
        // width={500} automatically provided
        // height={500} automatically provided
        // blurDataURL="data:..." automatically provided
        // Optionally allows to add a blurred version of the image while loading
        // placeholder="blur"
      />
      <p>Welcome to my homepage!</p>
    </>
  )
}

For dynamic or remote images, you'll have to provide width, height, and blurDataURL manually.

Configuration

In addition to using properties available to the Image component, you can optionally configure Image Optimization for more advanced use cases via blitz.config.js.

Domains

To enable Image Optimization for images hosted on an external website, use an absolute url for the Image src and specify which domains are allowed to be optimized. This is needed to ensure that external urls can't be abused.

module.exports = {
  images: {
    domains: ["example.com"],
  },
}

Loader

If you want to use a cloud provider to optimize images instead of using the Blitz' built-in Image Optimization, you can configure the loader and path prefix. This allows you to use relative urls for the Image src and automatically generate the correct absolute url for your provider.

module.exports = {
  images: {
    loader: "imgix",
    path: "https://example.com/myaccount/",
  },
}

The following Image Optimization cloud providers are supported:

  • Vercel: Works automatically when you deploy on Vercel, no configuration necessary. Learn more
  • Imgix: loader: 'imgix'
  • Cloudinary: loader: 'cloudinary'
  • Akamai: loader: 'akamai'
  • Custom: loader: 'custom' use a custom cloud provider by implementing the loader prop on the Image component
  • Default: Works automatically with blitz dev or blitz start

The Image component's default loader is not supported when using blitz export. However, other loader options will work.

The Image component's default loader uses the 'squoosh' library for image resizing and optimization. This library is quick to install and suitable for a dev server environment. For a production environment, it is strongly recommended that you install the optional sharp library by running yarn add sharp in your project directory. If sharp is already installed but can't be resolved you can manually pass the path to it via the BLITZ_SHARP_PATH environment variable e.g. BLITZ_SHARP_PATH=/tmp/node_modules/sharp

Caching

The following describes the caching algorithm for the default loader. For all other loaders, please refer to your cloud provider's documentation.

Images are optimized dynamically upon request and stored in the <distDir>/cache/images directory. The optimized image file will be served for subsequent requests until the expiration is reached. When a request is made that matches a cached but expired file, the cached file is deleted before generating a new optimized image and caching the new file.

The expiration (or rather Max Age) is defined by the upstream server's Cache-Control header.

If s-maxage is found in Cache-Control, it is used. If no s-maxage is found, then max-age is used. If no max-age is found, then minimumCacheTTL is used.

You can configure minimumCacheTTL to increase the cache duration when the upstream image does not include max-age.

You can configure deviceSizes and imageSizes to reduce the total number of possible generated images.

Advanced

The following configuration is for advanced use cases and is usually not necessary. If you choose to configure the properties below, you will override any changes to the Blitz defaults in future updates.

Device Sizes

In some cases, where you know the expected device widths from the users of your website, you can specify a list of device width breakpoints using the deviceSizes property. These widths are used when the Image component uses layout="responsive" or layout="fill" so that the correct image is served for the device visiting your website.

If no configuration is provided, the default below is used.

module.exports = {
  images: {
    deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
  },
}

Image Sizes

You can specify a list of image widths using the imageSizes property. These widths should be different (usually smaller) than the widths defined in deviceSizes because the arrays will be concatenated. These widths are used when the Image component uses layout="fixed" or layout="intrinsic".

If no configuration is provided, the default below is used.

module.exports = {
  images: {
    imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
  },
}

Minimum Cache TTL

You can configure the time to live (TTL) in seconds for cached optimized images. In many cases, its better to use a Static Image Import which will handle hashing file contents and caching the file forever.

module.exports = {
  images: {
    minimumCacheTTL: 60,
  },
}

If you need to add a Cache-Control header for the browser (not recommended), you can configure headers on the upstream image e.g. /some-asset.jpg not /_next/image itself.

Disable Static Imports

The default behavior allows you to import static files such as import icon from './icon.png and then pass that to the src property.

In some cases, you may wish to disable this feature if it conflicts with other plugins that expect the import to behave differently.

You can disable static image imports with the following configuration below.

module.exports = {
  images: {
    disableStaticImages: true,
  },
}

Image API

Image Optimization can be enabled via the Image component.

Usage

For an example, consider a project with the following files:

  • pages/index.js
  • public/me.png

We can serve an optimized image like so:

import { Image } from "blitz"

function Home() {
  return (
    <>
      <h1>My Homepage</h1>
      <Image
        src="/me.png"
        alt="Picture of the author"
        width={500}
        height={500}
      />
      <p>Welcome to my homepage!</p>
    </>
  )
}

export default Home

Required Props

The Image component requires the following properties.

src

Required and must be one of the following:

  1. A statically imported image file, as in the example code above, or
  2. A path string. This can be either an absolute external URL, or an internal path depending on the loader.

When using an external URL, you must add it to domains in blitz.config.js.

width

The width of the image, in pixels. Must be an integer without a unit.

Required, except for statically imported images, or those with layout="fill".

height

The height of the image, in pixels. Must be an integer without a unit.

Required, except for statically imported images, or those with layout="fill".

Optional Props

The <Image /> component optionally accepts the following properties.

layout

The layout behavior of the image as the viewport changes size. Defaults to intrinsic.

When fixed, the image dimensions will not change as the viewport changes (no responsiveness) similar to the native img element.

When intrinsic, the image will scale the dimensions down for smaller viewports but maintain the original dimensions for larger viewports.

When responsive, the image will scale the dimensions down for smaller viewports and scale up for larger viewports. Note: the responsive layout may not work correctly if the parent element uses a display value other than block such as display: flex or display: grid.

When fill, the image will stretch both width and height to the dimensions of the parent element, provided the parent element is relative. This is usually paired with the objectFit property. Ensure the parent element has position: relative in their stylesheet. Try it out:

loader

A custom function used to resolve URLs. Defaults to images object in blitz.config.js.

loader is a function returning a string, given the following parameters:

  • src
  • width
  • quality
import { Image } from "blitz"

const myLoader = ({ src, width, quality }) => {
  return `https://example.com/${src}?w=${width}&q=${quality || 75}`
}

const MyImage = (props) => {
  return (
    <Image
      loader={myLoader}
      src="me.png"
      alt="Picture of the author"
      width={500}
      height={500}
    />
  )
}

sizes

A string mapping media queries to device sizes. Defaults to 100vw.

We recommend setting sizes when layout="responsive" and your image will not be the same width as the viewport.

Learn more.

quality

The quality of the optimized image, an integer between 1 and 100 where 100 is the best quality. Defaults to 75.

priority

When true, the image will be considered high priority and preload.

Should only be used when the image is visible above the fold. Defaults to false.

placeholder

A placeholder to use while the image is loading, possible values are blur or empty. Defaults to empty.

When blur, the blurDataURL property will be used as the placeholder. If src is an object from a static import and the imported image is jpg, png, or webp, then blurDataURL will automatically be populated.

For dynamic images, you must provide the blurDataURL property. Solutions such as Plaiceholder can help with base64 generation.

When empty, there will be no placeholder while the image is loading, only empty space.

Try it out:

Advanced Props

In some cases, you may need more advanced usage. The Image component optionally accepts the following advanced properties.

objectFit

The image fit when using layout="fill".

Learn more.

objectPosition

The image position when using layout="fill".

Learn more.

onLoadingComplete

A callback function that is invoked once the image is completely loaded and the placeholder has been removed.

The onLoadingComplete function accepts one parameter, an object with the following properties:

loading

Caution

This property is only meant for advanced usage. Switching an image to load with eager will normally hurt performance.

We recommend using the priority property instead, which properly loads the image eagerly for nearly all use cases.

The loading behavior of the image. Defaults to lazy.

When lazy, defer loading the image until it reaches a calculated distance from the viewport.

When eager, load the image immediately.

Learn more.

blurDataURL

A Data URL to be used as a placeholder image before the src image successfully loads. Only takes effect when combined with placeholder="blur".

Must be a base64-encoded image. It will be enlarged and blurred, so a very small image (10px or less) is recommended. Including larger images as placeholders may harm your application performance.

Try it out:

You can also generate a solid color Data URL to match the image.

lazyBoundary

A string (with similar syntax to the margin property) that acts as the bounding box used to detect the intersection of the viewport with the image and trigger lazy loading. Defaults to "200px".

Learn more

unoptimized

When true, the source image will be served as-is instead of changing quality, size, or format. Defaults to false.

Other Props

Other properties on the Image component will be passed to the underlying img element with the exception of the following:


Idea for improving this page? Edit it on GitHub.