Course
Optimizing I
Next.js Mastery: From Fundamentals to Full-Stack
Unlock the power of Next.js with this comprehensive course! Starting with the basics, you’ll learn essential skills such as routing, data fetching, and styling. Progress through practical projects, including building your own React Notes app, to gain hands-on experience. Dive into the source code to understand the inner workings and core principles of Next.js. Perfect for developers with a basic knowledge of React and Node.js, this course ensures you’ll be ready to create high-performance full-stack applications efficiently. Join us and master Next.js, backed by industry experts and a supportive learning community.
Optimizing
In addition to using props, you can configure the image component in
next.config.js
.1. remotePatterns
To protect your application from malicious users, you need to configure
remotePatterns
when using external images:// next.config.jsmodule.exports = { images: { remotePatterns: [ { protocol: 'https', hostname: 'example.com', port: '', pathname: '/account123/**', }, ], },}
This example means that the
src
attribute value of next/image
must start with https://example.com/account123/
. Other protocols, hostnames, ports, or mismatched paths will return a 400 error.Here’s another example using wildcards:
// next.config.jsmodule.exports = { images: { remotePatterns: [ { protocol: 'https', hostname: '**.example.com', }, ], },}
This example means that the
src
attribute value of next/image
must start with https://xxx.example.com
, https://xxx.xxx.example.com
, https://xxx.xxx.xxx.example.com
, etc.Both
pathname
and hostname
can use wildcards, where:*
matches a single path segment or subdomain.**
matches any number of path segments or subdomains.
Note: The
**
syntax does not work in the middle of a pattern.2. domains
Since Next.js 14,
domains
has been deprecated in favor of the stricter remotePatterns
. Use it only when all content comes from domains you control.Similar to
remotePatterns
, the domains
option provides a list of hostnames for external images:// next.config.jsmodule.exports = { images: { domains: ['assets.acme.com'], },}
However, note that
domains
does not support wildcards and cannot restrict protocols, ports, or pathnames. Therefore, it is recommended to use remotePatterns
instead.3. loaderFile
If you don’t want to use Next.js's built-in image optimization API, you can configure your own with the
loaderFile
option in next.config.js
:// next.config.jsmodule.exports = { images: { loader: 'custom', loaderFile: './my/image/loader.js', },}
loaderFile
must point to a file relative to the root directory of your Next.js application. This file must export a default function that returns a string. Here’s an example:'use client'
export default function myImageLoader({ src, width, quality }) { return `https://example.com/${src}?w=${width}&q=${quality || 75}`}
This will apply to all
next/image
instances. If you need to modify individual images, use the loader
prop.4. deviceSizes
If you know the width of your users’ devices, you can use the
deviceSizes
option in next.config.js
to declare a series of device width breakpoints. These widths will be used to infer the correct image to load when the sizes
prop is used with the next/image
component.If not configured, the default value is:
// next.config.jsmodule.exports = { images: { deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840], },}
5. imageSizes
You can declare a series of image widths using the
imageSizes
option in next.config.js
.If not configured, the default value is:
// next.config.jsmodule.exports = { images: { imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], },}
imageSizes
and deviceSizes
both affect the final srcset
sizes generated for an image:
You might wonder why there are two arrays instead of just one since both are used to generate the final
srcset
. The answer is that deviceSizes
is used for handling large images, while imageSizes
is used for handling small images. Additionally, imageSizes
only takes effect when the sizes
prop is used, as shown in the following example:import Image from 'next/image'import profilePic from './image.png'
export default function Page() { return ( <Image src={profilePic} sizes="(max-width: 600px) 160px, 320px" alt="Picture of the author" /> )}
The corresponding
srcset
generated includes all sizes from both deviceSizes
and imageSizes
:
When you use the
sizes
prop, it indicates that the image’s width is less than the full screen width. All values in imageSizes
should be smaller than the smallest value in deviceSizes
.6. formats
Next.js’s default image optimization API automatically detects the supported image formats from the
Accept
request header.
If
Accept
matches multiple configured formats, the first one in the array will be used. Therefore, the order of the array is important. If no match is found, or if the source image is an animated image, the image optimization API will automatically fall back to the original image format.If not configured, the default value is:
// next.config.jsmodule.exports = { images: { formats: ['image/webp'], },}
You can enable AVIF format support with the following configuration:
// next.config.jsmodule.exports = { images: { formats: ['image/avif', 'image/webp'], },}
7. minimumCacheTTL
Images are dynamically optimized based on requests and stored in the
<distDir>/cache/images
directory. The optimized image files will be used for subsequent requests until the cache expires. When a file is found to be expired, the expired image will immediately become invalid, while the image will be re-optimized in the background and stored in the cache with a new expiration date.The cache status of the image is determined by reading the
x-nextjs-cache
header:MISS
: The path is not in the cache.STALE
: The path is cached but has exceeded the revalidation time; it will be updated in the background.HIT
: The path is in the cache and has not exceeded the revalidation time.
The expiration time can be defined in two ways:
One way is through the
minimumCacheTTL
option, and the other is through the Cache-Control
header, specifically using the max-age
field. If both s-maxage
and max-age
are present, s-maxage
takes precedence.If both methods are set, the larger value will be used.
The
minimumCacheTTL
option sets the expiration time for caching optimized images, in seconds. Here’s an example:// next.config.jsmodule.exports = { images: { minimumCacheTTL: 60, },}
If you need to change the caching behavior for each image, you can configure the
Cache-Control
header for image resources through headers.In most cases, it’s recommended to use static image imports, which automatically hash the file contents and use an immutable
Cache-Control
header.There is currently no mechanism to revalidate the cache, so it’s best to set the
minimumCacheTTL
to a lower value; otherwise, you may need to manually modify the src
prop or delete the <distDir>/cache/images
directory to update the cache.8. disableStaticImages
If the static image import feature conflicts with other plugins and you want to disable it:
// next.config.js module.exports = { images: { disableStaticImages: true, },}
9. dangerouslyAllowSVG
The default loader does not optimize SVG images. First, SVG is a vector format, meaning it can be resized losslessly. Second, SVG has many features similar to HTML/CSS, which can lead to vulnerabilities if not properly controlled by a content security policy.
If you need to use the default image optimization API to serve SVG images, set the
dangerouslyAllowSVG
value in next.config.js
:// next.config.jsmodule.exports = { images: { dangerouslyAllowSVG: true, contentDispositionType: 'attachment', contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;", },}
Next.js strongly recommends setting
contentDispositionType
to force the browser to download the image, and setting contentSecurityPolicy
to block scripts embedded in the image from executing.