Sponsor
ntab.devntab.dev 提升效率的新标签页组件
点击查看
Menu

图像(旧版)

示例

从 Next.js 13 开始,next/image 组件被重写以提高性能和开发者体验。为了提供向后兼容的升级方案,旧的 next/image 被重命名为 next/legacy/image

查看新的 next/image API 参考

对比

next/legacy/image 相比,新的 next/image 组件有以下变化:

  • 移除了 <img> 周围的 <span> 包装器,转而支持原生计算的纵横比
  • 添加了对规范 style 属性的支持
    • 移除 layout 属性,改用 styleclassName
    • 移除 objectFit 属性,改用 styleclassName
    • 移除 objectPosition 属性,改用 styleclassName
  • 移除 IntersectionObserver 实现,转而支持原生懒加载
    • 移除 lazyBoundary 属性,因为没有原生等效项
    • 移除 lazyRoot 属性,因为没有原生等效项
  • 移除 loader 配置,改用 loader 属性
  • alt 属性从可选改为必需
  • 更改 onLoadingComplete 回调以接收 <img> 元素的引用

必需属性

<Image /> 组件需要以下属性。

src

必须是以下之一:

使用默认 loader 时,还要考虑源图像的以下情况:

  • 当 src 是外部 URL 时,你还必须配置 remotePatterns
  • 当 src 是动画或未知格式(JPEG、PNG、WebP、AVIF、GIF、TIFF)时,图像将按原样提供
  • 当 src 是 SVG 格式时,除非启用 unoptimizeddangerouslyAllowSVG,否则将被阻止

width

width 属性可以表示渲染宽度或原始宽度(以像素为单位),具体取决于 layoutsizes 属性。

使用 layout="intrinsic"layout="fixed" 时,width 属性表示渲染宽度(以像素为单位),因此会影响图像的显示大小。

使用 layout="responsive"layout="fill" 时,width 属性表示原始宽度(以像素为单位),因此只会影响纵横比。

除了静态导入的图像layout="fill" 的图像外,width 属性是必需的。

height

height 属性可以表示渲染高度或原始高度(以像素为单位),具体取决于 layoutsizes 属性。

使用 layout="intrinsic"layout="fixed" 时,height 属性表示渲染高度(以像素为单位),因此会影响图像的显示大小。

使用 layout="responsive"layout="fill" 时,height 属性表示原始高度(以像素为单位),因此只会影响纵横比。

除了静态导入的图像layout="fill" 的图像外,height 属性是必需的。

可选属性

<Image /> 组件除了必需属性外,还接受许多其他属性。本节描述图像组件最常用的属性。关于更少使用的属性的详细信息,请参见高级属性部分。

layout

图像在视口大小变化时的布局行为。

layout行为srcSetsizes是否有包装器和尺寸器
intrinsic(默认)缩小以适应容器宽度,最大为图像原始大小1x2x(基于 imageSizes不适用
fixed精确调整到 widthheight1x2x(基于 imageSizes不适用
responsive缩放以适应容器宽度640w750w、... 2048w3840w(基于 imageSizesdeviceSizes100vw
fill在 X 和 Y 轴上增长以填充容器640w750w、... 2048w3840w(基于 imageSizesdeviceSizes100vw
  • 演示 intrinsic 布局(默认)
    • 使用 intrinsic 时,图像将为较小的视口缩小尺寸,但在较大的视口中保持原始尺寸。
  • 演示 fixed 布局
    • 使用 fixed 时,图像尺寸不会随视口变化(无响应性),类似于原生 img 元素。
  • 演示 responsive 布局
    • 使用 responsive 时,图像将为较小的视口缩小尺寸,并为较大的视口放大。
    • 确保父元素在样式表中使用 display: block
  • 演示 fill 布局
    • 使用 fill 时,图像将拉伸宽度和高度以匹配父元素的尺寸,前提是父元素是相对定位的。
    • 这通常与 objectFit 属性配对使用。
    • 确保父元素在样式表中有 position: relative
  • 演示背景图像

loader

用于解析 URL 的自定义函数。在图像组件上将 loader 设置为属性会覆盖 next.config.jsimages 部分中定义的默认 loader

loader 是一个函数,根据以下参数返回图像的 URL 字符串:

以下是使用自定义 loader 的示例:

import Image from 'next/legacy/image'
 
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="作者的图片"
      width={500}
      height={500}
    />
  )
}

sizes

一个字符串,提供关于图像在不同断点处的宽度信息。sizes 的值对于使用 layout="responsive"layout="fill" 的图像的性能有很大影响。对于使用 layout="intrinsic"layout="fixed" 的图像,它将被忽略。

sizes 属性与图像性能相关,有两个重要目的:

首先,sizes 的值由浏览器用于确定从 next/legacy/image 自动生成的源集中下载哪个大小的图像。当浏览器选择时,它尚不知道页面上图像的大小,因此选择一个与视口大小相同或更大的图像。sizes 属性允许你告诉浏览器图像实际上会比全屏小。如果不指定 sizes 值,则使用默认值 100vw(全屏宽度)。

其次,sizes 值被解析并用于修剪自动创建的源集中的值。如果 sizes 属性包含 50vw 等表示视口宽度百分比的大小,则源集将被修剪,不包含任何永远不会必要的过小值。

例如,如果你知道你的样式会导致图像在移动设备上全宽,在平板电脑上为 2 列布局,在桌面显示器上为 3 列布局,你应该包含如下 sizes 属性:

import Image from 'next/legacy/image'
const Example = () => (
  <div className="grid-element">
    <Image
      src="/example.png"
      layout="fill"
      sizes="(max-width: 768px) 100vw,
              (max-width: 1200px) 50vw,
              33vw"
    />
  </div>
)

这个示例 sizes 可能对性能指标产生显著影响。如果没有 sizes,从服务器选择的图像将比所需宽度大 3 倍。因为文件大小与宽度的平方成正比,所以没有 sizes,用户将下载一个比必要大 9 倍的图像。

了解更多关于 srcsetsizes

quality

优化图像的质量,1 到 100 之间的整数,其中 100 是最佳质量。默认为 75

priority

为 true 时,图像将被视为高优先级并预加载。对于使用 priority 的图像,懒加载会自动禁用。

你应该在任何被检测为最大内容绘制(Largest Contentful Paint,LCP)元素的图像上使用 priority 属性。在不同的视窗大小下,可能会有多个优先级图像。

仅在图像位于折叠线以上时使用。默认为 false

占位符

在图像加载时使用的占位符。可能的值为 blurempty。默认为 empty

当为 blur 时,将使用 blurDataURL 属性作为占位符。如果 src 是来自静态导入的对象,且导入的图像是 .jpg.png.webp.avif,那么 blurDataURL 将自动填充。

对于动态图像,你必须提供 blurDataURL 属性。像 Plaiceholder 这样的解决方案可以帮助生成 base64

当为 empty 时,图像加载时将没有占位符,只有空白空间。

试试看:

高级属性

在某些情况下,你可能需要更高级的用法。<Image /> 组件可选择接受以下高级属性。

样式

允许传递 CSS 样式到底层图像元素。

请注意,所有 layout 模式都会对图像元素应用自己的样式,这些自动样式优先于 style 属性。

还要记住,必需的 widthheight 属性可能会与你的样式交互。如果你使用样式修改图像的 width,还必须设置 height="auto" 样式,否则你的图像会被扭曲。

objectFit

定义在使用 layout="fill" 时图像如何适应其父容器。

这个值被传递给 src 图像的 object-fit CSS 属性

objectPosition

定义在使用 layout="fill" 时图像在其父元素中的位置。

这个值被传递给应用于图像的 object-position CSS 属性

onLoadingComplete

一个回调函数,在图像完全加载且占位符已移除时调用。

onLoadingComplete 函数接受一个参数,是一个包含以下属性的对象:

loading

图像的加载行为。默认为 lazy

当为 lazy 时,延迟加载图像直到它达到从视窗计算的距离。

当为 eager 时,立即加载图像。

了解更多

blurDataURL

一个在 src 图像成功加载之前用作占位符图像的数据 URL。仅在与 placeholder="blur" 结合使用时生效。

必须是 base64 编码的图像。它将被放大和模糊,因此推荐使用非常小的图像(10像素或更小)。将较大的图像作为占位符可能会损害你的应用性能。

试试看:

你还可以生成一个纯色数据 URL 来匹配图像。

lazyBoundary

一个字符串(语法类似于边距属性),作为用于检测视窗与图像相交并触发延迟加载的边界框。默认为 "200px"

如果图像嵌套在根文档以外的可滚动父元素中,你还需要分配 lazyRoot 属性。

了解更多

lazyRoot

指向可滚动父元素的 React Ref。默认为 null(文档视窗)。

Ref 必须指向 DOM 元素或一个转发 Ref 到底层 DOM 元素的 React 组件。

指向 DOM 元素的示例

import Image from 'next/legacy/image'
import React from 'react'
 
const Example = () => {
  const lazyRoot = React.useRef(null)
 
  return (
    <div ref={lazyRoot} style={{ overflowX: 'scroll', width: '500px' }}>
      <Image lazyRoot={lazyRoot} src="/one.jpg" width="500" height="500" />
      <Image lazyRoot={lazyRoot} src="/two.jpg" width="500" height="500" />
    </div>
  )
}

指向 React 组件的示例

import Image from 'next/legacy/image'
import React from 'react'
 
const Container = React.forwardRef((props, ref) => {
  return (
    <div ref={ref} style={{ overflowX: 'scroll', width: '500px' }}>
      {props.children}
    </div>
  )
})
 
const Example = () => {
  const lazyRoot = React.useRef(null)
 
  return (
    <Container ref={lazyRoot}>
      <Image lazyRoot={lazyRoot} src="/one.jpg" width="500" height="500" />
      <Image lazyRoot={lazyRoot} src="/two.jpg" width="500" height="500" />
    </Container>
  )
}

了解更多

unoptimized

为 true 时,源图像将按原样从 src 提供,不会更改质量、大小或格式。默认为 false

这对于不需要优化的图像很有用,如小图像(小于 1KB)、矢量图像(SVG)或动画图像(GIF)。

import Image from 'next/image'
 
const UnoptimizedImage = (props) => {
  return <Image {...props} unoptimized />
}

自 Next.js 12.3.0 起,可以通过在 next.config.js 中更新以下配置来为所有图像分配此属性:

next.config.js
module.exports = {
  images: {
    unoptimized: true,
  },
}

其他属性

<Image /> 组件上的其他属性将传递给底层的 img 元素,但以下除外:

配置选项

远程模式

为了保护你的应用免受恶意用户的攻击,使用外部图像需要进行配置。这确保只有来自你账户的外部图像可以从 Next.js 图像优化 API 提供服务。这些外部图像可以在 next.config.js 文件中使用 remotePatterns 属性进行配置,如下所示:

next.config.js
module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'example.com',
        port: '',
        pathname: '/account123/**',
        search: '',
      },
    ],
  },
}

值得注意的是:上面的示例将确保 next/legacy/imagesrc 属性必须以 https://example.com/account123/ 开头,且不能有查询字符串。任何其他协议、主机名、端口或不匹配的路径都将响应 400 错误请求。

下面是在 next.config.js 文件中使用通配符模式的 remotePatterns 属性的示例:

next.config.js
module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: '**.example.com',
        port: '',
        search: '',
      },
    ],
  },
}

值得注意的是:上面的示例将确保 next/legacy/imagesrc 属性必须以 https://img1.example.comhttps://me.avatar.example.com 或任意数量的子域开头。它不能有端口或查询字符串。任何其他协议或不匹配的主机名都将响应 400 错误请求。

通配符模式可用于 pathnamehostname,并具有以下语法:

  • * 匹配单个路径段或子域
  • ** 匹配结尾的任意数量路径段或开头的任意数量子域

** 语法不能在模式中间使用。

值得注意的是:省略 protocolportpathnamesearch 时,则默认为通配符 **。不建议这样做,因为它可能允许恶意行为者优化你不希望的 URL。

下面是 next.config.js 文件中使用 searchremotePatterns 属性的示例:

next.config.js
module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'assets.example.com',
        search: '?v=1727111025337',
      },
    ],
  },
}

值得注意的是:上面的示例将确保 next/legacy/imagesrc 属性必须以 https://assets.example.com 开头,且必须具有完全相同的查询字符串 ?v=1727111025337。任何其他协议或查询字符串都将响应 400 错误请求。

域名

警告:自 Next.js 14 起已弃用,取而代之的是严格的 remotePatterns,以保护你的应用免受恶意用户的攻击。仅在你拥有域名提供的所有内容时才使用 domains

remotePatterns 类似,domains 配置可用于提供外部图像的允许主机名列表。

但是,domains 配置不支持通配符模式匹配,也无法限制协议、端口或路径名。

下面是 next.config.js 文件中 domains 属性的示例:

next.config.js
module.exports = {
  images: {
    domains: ['assets.acme.com'],
  },
}

加载器配置

如果你想使用云提供商来优化图像,而不是使用 Next.js 内置的图像优化 API,你可以在 next.config.js 文件中配置 loader 和路径前缀。这允许你对图像 src 使用相对 URL,并自动为你的提供商生成正确的绝对 URL。

next.config.js
module.exports = {
  images: {
    loader: 'imgix',
    path: 'https://example.com/myaccount/',
  },
}

内置加载器

以下是包含的图像优化云提供商:

  • 默认:在 next devnext start 或自定义服务器中自动工作
  • Vercel:在 Vercel 上部署时自动工作,无需配置。了解更多
  • Imgixloader: 'imgix'
  • Cloudinaryloader: 'cloudinary'
  • Akamailoader: 'akamai'
  • 自定义:loader: 'custom' 通过在 next/legacy/image 组件上实现 loader 属性来使用自定义云提供商

如果你需要不同的提供商,可以在 next/legacy/image 中使用 loader 属性。

使用 output: 'export' 无法在构建时优化图像,只能按需优化。要在 output: 'export' 中使用 next/legacy/image,你需要使用与默认不同的加载器。在讨论中阅读更多。

高级

以下配置适用于高级用例,通常不是必需的。如果选择配置以下属性,你将覆盖未来更新中对 Next.js 默认值的任何更改。

设备尺寸

如果你知道用户的预期设备宽度,可以在 next.config.js 中使用 deviceSizes 属性指定设备宽度断点列表。当 next/legacy/image 组件使用 layout="responsive"layout="fill" 时,这些宽度用于确保为用户的设备提供正确的图像。

如果未提供配置,则使用以下默认值。

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

图像尺寸

你可以在 next.config.js 文件中使用 images.imageSizes 属性指定图像宽度列表。这些宽度与设备尺寸数组连接,形成用于生成图像 srcset 的完整尺寸数组。

有两个单独列表的原因是,imageSizes 仅用于提供 sizes 属性的图像,这表明图像小于屏幕全宽。因此,imageSizes 中的尺寸应该都小于 deviceSizes 中的最小尺寸。

如果未提供配置,则使用以下默认值。

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

可接受的格式

默认的图像优化 API 将通过请求的 Accept 标头自动检测浏览器支持的图像格式,以确定最佳输出格式。

如果 Accept 标头匹配多个配置的格式,则使用数组中的第一个匹配项。因此,数组顺序很重要。如果没有匹配(或源图像是动画),图像优化 API 将回退到原始图像的格式。

如果未提供配置,则使用以下默认值。

next.config.js
module.exports = {
  images: {
    formats: ['image/webp'],
  },
}

你可以启用 AVIF 支持,如果浏览器不支持 AVIF,则回退到源图像的原始格式:

next.config.js
module.exports = {
  images: {
    formats: ['image/avif'],
  },
}

值得注意的是

  • 我们仍然建议在大多数用例中使用 WebP。
  • AVIF 的编码通常需要 50% 的时间,但与 WebP 相比压缩率降低 20%。这意味着第一次请求图像时通常会较慢,而后续缓存的请求会更快。
  • 如果你使用代理/CDN 自托管 Next.js,必须配置代理以转发 Accept 标头。

缓存行为

以下描述了默认加载器的缓存算法。对于所有其他加载器,请参考你的云提供商的文档。

图像在请求时动态优化,并存储在 <distDir>/cache/images 目录中。优化后的图像文件将在后续请求中提供,直到到期。当请求与已缓存但已过期的文件匹配时,过期的图像将立即以陈旧状态提供。然后,图像在后台重新优化(也称为重新验证)并保存到缓存中,并带有新的到期日期。

可以通过读取 x-nextjs-cache(在 Vercel 上部署时为 x-vercel-cache)响应标头的值来确定图像的缓存状态。可能的值如下:

  • MISS - 路径不在缓存中(最多发生一次,在第一次访问时)
  • STALE - 路径在缓存中,但超过了重新验证时间,因此将在后台更新
  • HIT - 路径在缓存中,且未超过重新验证时间

到期(或最大年龄)由 minimumCacheTTL 配置或上游图像 Cache-Control 标头中的较大者定义。具体来说,使用 Cache-Control 标头的 max-age 值。如果同时找到 s-maxagemax-age,则优先使用 s-maxagemax-age 也会传递给任何下游客户端,包括 CDN 和浏览器。

  • 当上游图像不包含 Cache-Control 标头或值非常低时,你可以配置 minimumCacheTTL 以增加缓存持续时间。
  • 你可以配置 deviceSizesimageSizes 以减少可生成图像的总数。
  • 你可以配置格式以禁用多种格式,只使用单一图像格式。

最小缓存 TTL

你可以为缓存的优化图像配置生存时间(TTL)(以秒为单位)。在许多情况下,使用静态图像导入更好,它将自动对文件内容进行哈希处理,并使用 Cache-Control 标头 immutable 永久缓存图像。

next.config.js
module.exports = {
  images: {
    minimumCacheTTL: 60,
  },
}

优化图像的到期(或最大年龄)由 minimumCacheTTL 或上游图像 Cache-Control 标头中的较大者定义。

如果需要更改每个图像的缓存行为,可以配置 headers 以在上游图像上设置 Cache-Control 标头(例如 /some-asset.jpg,而不是 /_next/image 本身)。

目前没有使缓存失效的机制,因此最好保持 minimumCacheTTL 较低。否则,你可能需要手动更改 src 属性或删除 <distDir>/cache/images

禁用静态导入

默认行为允许你导入静态文件,如 import icon from './icon.png',然后将其传递给 src 属性。

在某些情况下,如果它与期望导入行为不同的其他插件冲突,你可能希望禁用此功能。

你可以在 next.config.js 中禁用静态图像导入:

next.config.js
module.exports = {
  images: {
    disableStaticImages: true,
  },
}

危险地允许 SVG

默认的加载器不优化 SVG 图像,原因如下。首先,SVG 是一种矢量格式,意味着可以无损调整大小。其次,SVG 具有许多类似 HTML/CSS 的特性,如果没有适当的内容安全策略(CSP)标头,可能会导致漏洞。

因此,我们建议在 src 属性已知为 SVG 时使用 unoptimized 属性。当 src".svg" 结尾时,这会自动发生。

但是,如果你需要使用默认图像优化 API 提供 SVG 图像,可以在 next.config.js 中设置 dangerouslyAllowSVG

next.config.js
module.exports = {
  images: {
    dangerouslyAllowSVG: true,
    contentDispositionType: 'attachment',
    contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
  },
}

另外,强烈建议设置 contentDispositionType 以强制浏览器下载图像,以及设置 contentSecurityPolicy 以防止图像中嵌入的脚本执行。

contentDispositionType

默认的加载器Content-Disposition 标头设置为 attachment,以提供额外的保护,因为 API 可以提供任意远程图像。

默认值为 attachment,强制浏览器在直接访问时下载图像。当 dangerouslyAllowSVG 为 true 时,这尤其重要。

你可以选择配置 inline 以允许浏览器在直接访问时渲染图像,而无需下载。

next.config.js
module.exports = {
  images: {
    contentDispositionType: 'inline',
  },
}

动画图像

默认的加载器将自动绕过动画图像的图像优化,并按原样提供图像。

对动画文件的自动检测是尽力而为的,并支持 GIF、APNG 和 WebP。如果你想为特定的动画图像显式绕过图像优化,请使用 unoptimized 属性。

版本历史

版本变更
v13.0.0next/image 重命名为 next/legacy/image