图像(旧版)
示例
从 Next.js 13 开始,next/image
组件被重写以提高性能和开发者体验。为了提供向后兼容的升级方案,旧的 next/image
被重命名为 next/legacy/image
。
查看新的 next/image
API 参考
对比
与 next/legacy/image
相比,新的 next/image
组件有以下变化:
- 移除了
<img>
周围的<span>
包装器,转而支持原生计算的纵横比 - 添加了对规范
style
属性的支持- 移除
layout
属性,改用style
或className
- 移除
objectFit
属性,改用style
或className
- 移除
objectPosition
属性,改用style
或className
- 移除
- 移除
IntersectionObserver
实现,转而支持原生懒加载- 移除
lazyBoundary
属性,因为没有原生等效项 - 移除
lazyRoot
属性,因为没有原生等效项
- 移除
- 移除
loader
配置,改用loader
属性 - 将
alt
属性从可选改为必需 - 更改
onLoadingComplete
回调以接收<img>
元素的引用
必需属性
<Image />
组件需要以下属性。
src
必须是以下之一:
使用默认 loader 时,还要考虑源图像的以下情况:
- 当 src 是外部 URL 时,你还必须配置 remotePatterns
- 当 src 是动画或未知格式(JPEG、PNG、WebP、AVIF、GIF、TIFF)时,图像将按原样提供
- 当 src 是 SVG 格式时,除非启用
unoptimized
或dangerouslyAllowSVG
,否则将被阻止
width
width
属性可以表示渲染宽度或原始宽度(以像素为单位),具体取决于 layout
和 sizes
属性。
使用 layout="intrinsic"
或 layout="fixed"
时,width
属性表示渲染宽度(以像素为单位),因此会影响图像的显示大小。
使用 layout="responsive"
或 layout="fill"
时,width
属性表示原始宽度(以像素为单位),因此只会影响纵横比。
除了静态导入的图像或 layout="fill"
的图像外,width
属性是必需的。
height
height
属性可以表示渲染高度或原始高度(以像素为单位),具体取决于 layout
和 sizes
属性。
使用 layout="intrinsic"
或 layout="fixed"
时,height
属性表示渲染高度(以像素为单位),因此会影响图像的显示大小。
使用 layout="responsive"
或 layout="fill"
时,height
属性表示原始高度(以像素为单位),因此只会影响纵横比。
除了静态导入的图像或 layout="fill"
的图像外,height
属性是必需的。
可选属性
<Image />
组件除了必需属性外,还接受许多其他属性。本节描述图像组件最常用的属性。关于更少使用的属性的详细信息,请参见高级属性部分。
layout
图像在视口大小变化时的布局行为。
layout | 行为 | srcSet | sizes | 是否有包装器和尺寸器 |
---|---|---|---|---|
intrinsic (默认) | 缩小以适应容器宽度,最大为图像原始大小 | 1x 、2x (基于 imageSizes) | 不适用 | 是 |
fixed | 精确调整到 width 和 height | 1x 、2x (基于 imageSizes) | 不适用 | 是 |
responsive | 缩放以适应容器宽度 | 640w 、750w 、... 2048w 、3840w (基于 imageSizes 和 deviceSizes) | 100vw | 是 |
fill | 在 X 和 Y 轴上增长以填充容器 | 640w 、750w 、... 2048w 、3840w (基于 imageSizes 和 deviceSizes) | 100vw | 是 |
- 演示
intrinsic
布局(默认)- 使用
intrinsic
时,图像将为较小的视口缩小尺寸,但在较大的视口中保持原始尺寸。
- 使用
- 演示
fixed
布局- 使用
fixed
时,图像尺寸不会随视口变化(无响应性),类似于原生img
元素。
- 使用
- 演示
responsive
布局- 使用
responsive
时,图像将为较小的视口缩小尺寸,并为较大的视口放大。 - 确保父元素在样式表中使用
display: block
。
- 使用
- 演示
fill
布局- 使用
fill
时,图像将拉伸宽度和高度以匹配父元素的尺寸,前提是父元素是相对定位的。 - 这通常与
objectFit
属性配对使用。 - 确保父元素在样式表中有
position: relative
。
- 使用
- 演示背景图像
loader
用于解析 URL 的自定义函数。在图像组件上将 loader 设置为属性会覆盖 next.config.js
的 images
部分中定义的默认 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 倍的图像。
了解更多关于 srcset
和 sizes
:
quality
优化图像的质量,1 到 100 之间的整数,其中 100 是最佳质量。默认为 75
。
priority
为 true 时,图像将被视为高优先级并预加载。对于使用 priority
的图像,懒加载会自动禁用。
你应该在任何被检测为最大内容绘制(Largest Contentful Paint,LCP)元素的图像上使用 priority
属性。在不同的视窗大小下,可能会有多个优先级图像。
仅在图像位于折叠线以上时使用。默认为 false
。
占位符
在图像加载时使用的占位符。可能的值为 blur
或 empty
。默认为 empty
。
当为 blur
时,将使用 blurDataURL
属性作为占位符。如果 src
是来自静态导入的对象,且导入的图像是 .jpg
、.png
、.webp
或 .avif
,那么 blurDataURL
将自动填充。
对于动态图像,你必须提供 blurDataURL
属性。像 Plaiceholder 这样的解决方案可以帮助生成 base64
。
当为 empty
时,图像加载时将没有占位符,只有空白空间。
试试看:
高级属性
在某些情况下,你可能需要更高级的用法。<Image />
组件可选择接受以下高级属性。
样式
允许传递 CSS 样式到底层图像元素。
请注意,所有 layout
模式都会对图像元素应用自己的样式,这些自动样式优先于 style
属性。
还要记住,必需的 width
和 height
属性可能会与你的样式交互。如果你使用样式修改图像的 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
中更新以下配置来为所有图像分配此属性:
module.exports = {
images: {
unoptimized: true,
},
}
其他属性
<Image />
组件上的其他属性将传递给底层的 img
元素,但以下除外:
srcSet
。改用设备尺寸。ref
。改用onLoadingComplete
。decoding
。它始终为"async"
。
配置选项
远程模式
为了保护你的应用免受恶意用户的攻击,使用外部图像需要进行配置。这确保只有来自你账户的外部图像可以从 Next.js 图像优化 API 提供服务。这些外部图像可以在 next.config.js
文件中使用 remotePatterns
属性进行配置,如下所示:
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'example.com',
port: '',
pathname: '/account123/**',
search: '',
},
],
},
}
值得注意的是:上面的示例将确保
next/legacy/image
的src
属性必须以https://example.com/account123/
开头,且不能有查询字符串。任何其他协议、主机名、端口或不匹配的路径都将响应 400 错误请求。
下面是在 next.config.js
文件中使用通配符模式的 remotePatterns
属性的示例:
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: '**.example.com',
port: '',
search: '',
},
],
},
}
值得注意的是:上面的示例将确保
next/legacy/image
的src
属性必须以https://img1.example.com
或https://me.avatar.example.com
或任意数量的子域开头。它不能有端口或查询字符串。任何其他协议或不匹配的主机名都将响应 400 错误请求。
通配符模式可用于 pathname
和 hostname
,并具有以下语法:
*
匹配单个路径段或子域**
匹配结尾的任意数量路径段或开头的任意数量子域
**
语法不能在模式中间使用。
值得注意的是:省略
protocol
、port
、pathname
或search
时,则默认为通配符**
。不建议这样做,因为它可能允许恶意行为者优化你不希望的 URL。
下面是 next.config.js
文件中使用 search
的 remotePatterns
属性的示例:
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'assets.example.com',
search: '?v=1727111025337',
},
],
},
}
值得注意的是:上面的示例将确保
next/legacy/image
的src
属性必须以https://assets.example.com
开头,且必须具有完全相同的查询字符串?v=1727111025337
。任何其他协议或查询字符串都将响应 400 错误请求。
域名
警告:自 Next.js 14 起已弃用,取而代之的是严格的
remotePatterns
,以保护你的应用免受恶意用户的攻击。仅在你拥有域名提供的所有内容时才使用domains
。
与 remotePatterns
类似,domains
配置可用于提供外部图像的允许主机名列表。
但是,domains
配置不支持通配符模式匹配,也无法限制协议、端口或路径名。
下面是 next.config.js
文件中 domains
属性的示例:
module.exports = {
images: {
domains: ['assets.acme.com'],
},
}
加载器配置
如果你想使用云提供商来优化图像,而不是使用 Next.js 内置的图像优化 API,你可以在 next.config.js
文件中配置 loader
和路径前缀。这允许你对图像 src
使用相对 URL,并自动为你的提供商生成正确的绝对 URL。
module.exports = {
images: {
loader: 'imgix',
path: 'https://example.com/myaccount/',
},
}
内置加载器
以下是包含的图像优化云提供商:
- 默认:在
next dev
、next start
或自定义服务器中自动工作 - Vercel:在 Vercel 上部署时自动工作,无需配置。了解更多
- Imgix:
loader: 'imgix'
- Cloudinary:
loader: 'cloudinary'
- Akamai:
loader: '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"
时,这些宽度用于确保为用户的设备提供正确的图像。
如果未提供配置,则使用以下默认值。
module.exports = {
images: {
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
},
}
图像尺寸
你可以在 next.config.js
文件中使用 images.imageSizes
属性指定图像宽度列表。这些宽度与设备尺寸数组连接,形成用于生成图像 srcset 的完整尺寸数组。
有两个单独列表的原因是,imageSizes
仅用于提供 sizes
属性的图像,这表明图像小于屏幕全宽。因此,imageSizes
中的尺寸应该都小于 deviceSizes
中的最小尺寸。
如果未提供配置,则使用以下默认值。
module.exports = {
images: {
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
},
}
可接受的格式
默认的图像优化 API 将通过请求的 Accept
标头自动检测浏览器支持的图像格式,以确定最佳输出格式。
如果 Accept
标头匹配多个配置的格式,则使用数组中的第一个匹配项。因此,数组顺序很重要。如果没有匹配(或源图像是动画),图像优化 API 将回退到原始图像的格式。
如果未提供配置,则使用以下默认值。
module.exports = {
images: {
formats: ['image/webp'],
},
}
你可以启用 AVIF 支持,如果浏览器不支持 AVIF,则回退到源图像的原始格式:
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-maxage
和 max-age
,则优先使用 s-maxage
。max-age
也会传递给任何下游客户端,包括 CDN 和浏览器。
- 当上游图像不包含
Cache-Control
标头或值非常低时,你可以配置minimumCacheTTL
以增加缓存持续时间。 - 你可以配置
deviceSizes
和imageSizes
以减少可生成图像的总数。 - 你可以配置格式以禁用多种格式,只使用单一图像格式。
最小缓存 TTL
你可以为缓存的优化图像配置生存时间(TTL)(以秒为单位)。在许多情况下,使用静态图像导入更好,它将自动对文件内容进行哈希处理,并使用 Cache-Control
标头 immutable
永久缓存图像。
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
中禁用静态图像导入:
module.exports = {
images: {
disableStaticImages: true,
},
}
危险地允许 SVG
默认的加载器不优化 SVG 图像,原因如下。首先,SVG 是一种矢量格式,意味着可以无损调整大小。其次,SVG 具有许多类似 HTML/CSS 的特性,如果没有适当的内容安全策略(CSP)标头,可能会导致漏洞。
因此,我们建议在 src
属性已知为 SVG 时使用 unoptimized
属性。当 src
以 ".svg"
结尾时,这会自动发生。
但是,如果你需要使用默认图像优化 API 提供 SVG 图像,可以在 next.config.js
中设置 dangerouslyAllowSVG
:
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
以允许浏览器在直接访问时渲染图像,而无需下载。
module.exports = {
images: {
contentDispositionType: 'inline',
},
}
动画图像
默认的加载器将自动绕过动画图像的图像优化,并按原样提供图像。
对动画文件的自动检测是尽力而为的,并支持 GIF、APNG 和 WebP。如果你想为特定的动画图像显式绕过图像优化,请使用 unoptimized 属性。
版本历史
版本 | 变更 |
---|---|
v13.0.0 | next/image 重命名为 next/legacy/image |