跳到主要内容

图像优化

根据Web Almanac的数据,图像占据了典型网站页面权重的很大一部分,并且对网站的LCP性能有相当大的影响。

Next.js的Image组件通过扩展HTML <img> 元素,提供了自动图像优化的功能:

  • 尺寸优化: 为每个设备自动提供正确尺寸的图像,使用现代图像格式如WebP和AVIF。

  • 视觉稳定性: 在图像加载时自动防止布局移位。

  • 更快的页面加载: 使用原生浏览器懒加载,仅在图像进入视口时加载,可选择使用模糊占位符。

  • 资产灵活性: 需要时对图像进行按需调整大小,即使是存储在远程服务器上的图像。

🎥 观看:学习如何使用next/image → YouTube (9分钟)

使用

import Image from 'next/image'

然后,您可以为图像定义src(可以是本地或远程)。

本地图像

要使用本地图像,请import您的 .jpg.png.webp 图像文件。

Next.js 将根据导入的文件自动确定图像的widthheight。这些值用于在图像加载时防止累积布局移位。

app/page.js
import Image from 'next/image'
import profilePic from './me.png'

export default function Page() {
return (
<Image
src={profilePic}
alt="Picture of the author"
// width={500} 会自动提供
// height={500} 会自动提供
// blurDataURL="data:..." 会自动提供
// placeholder="blur" // 可选,加载时的模糊占位符
/>
)
}
注意

不支持动态的 await import()require()。导入必须是静态的,以便在构建时进行分析。

远程图像

要使用远程图像,src 属性应该是一个 URL 字符串。

由于 Next.js 在构建过程中无法访问远程文件,您需要手动提供 widthheight 和可选的 blurDataURL 属性。

widthheight属性用于推断图像的正确纵横比,并避免加载图像时发生布局偏移。 宽度和高度并不决定图像文件的渲染大小。 了解有关图像大小 调整的更多信息。

import Image from 'next/image'

export default function Page() {
return (
<Image
src="https://s3.amazonaws.com/my-bucket/profile.png"
alt="Picture of the author"
width={500}
height={500}
/>
)
}

为了安全地允许优化图像,请在 next.config.js 中定义受支持的 URL 模式列表。 尽量具体化以防止恶意使用。例如,以下配置仅允许特定 AWS S3 存储桶的图像:

next.config.js
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 's3.amazonaws.com',
port: '',
pathname: '/my-bucket/**',
},
],
},
}

了解有关 remotePatterns 配置的更多信息。如果要使用图像 src 的相对 URL,请使用一个 loader

域名

有时您可能希望优化远程图像,但仍然使用内置的 Next.js 图像优化 API。 为此,请将 loader 设置为其默认设置,并为 Imagesrc 属性输入绝对 URL

为防止恶意用户对应用程序造成损害,必须定义一个您打算与 next/image 组件一起使用的远程主机名列表。

了解有关 remotePatterns 配置的更多信息

加载程序

请注意,在前面的例子中,为本地图像提供了一个部分 URL("/me.png")。这是因为加载程序架构的存在。

加载程序是一个生成图像 URL 的函数。它修改提供的 src, 并生成多个 URL 以请求不同大小的图像。 这些多个 URL 用于自动生成 srcset, 以便站点访问者将得到适合其视口大小的图像。

Next.js 应用程序的默认加载程序使用内置的图像优化 API,该 API 优化来自 Web 任何位置的图像, 然后直接从 Next.js Web 服务器提供它们。如果您想直接从 CDN 或图像服务器提供图像, 可以使用几行 JavaScript 编写自己的加载程序函数。

您可以使用 loader 属性 为每个图像定义一个加载程序, 或者使用 loaderFile 配置 在应用程序级别定义加载程序。

优先级

您应该为每个页面的 Largest Contentful Paint(LCP)元素添加priority 属性。 这样做允许 Next.js 为该图像加载设置特殊的优先级(例如通过 preload 标签或优先提示),从而提高 LCP。

LCP 元素通常是页面视口内可见的最大图像或文本块。 运行 next dev 时,如果 LCP 元素是一个没有 priority 属性的 <Image>,您将看到控制台警告。

一旦您确定了 LCP 图像,可以像这样添加属性:

import Image from 'next/image'
import profilePic from '../public/me.png'

export default function Page() {
return <Image src={profilePic} alt="Picture of the author" priority />
}

next/image 组件文档中查看有关 priority更多信息

图像大小

图像最常导致性能问题的方式之一是布局移位,即图像在加载时将页面上的其他元素推动到周围。 这种性能问题对用户来说非常恼人,因此它有自己的核心Web Vitals,称为Cumulative Layout Shift(CLS)。 避免基于图像的布局移位的方法是始终调整图像的大小。这允许浏览器在加载之前准确地保留足够的空间。

由于 next/image 旨在确保良好的性能结果,因此不能以导致布局移位的方式使用它,并且必须以以下三种方式之一调整大小:

  • 自动,使用静态导入
  • 显式,通过包含 widthheight 属性
  • 隐式,通过使用 fill,使图像扩展以填充其父元素。

如果我不知道我的图像大小怎么办?

如果您从不知道图像大小的源访问图像,有几件事情可以做:

使用 fill:

fill 属性允许图像按其父元素的大小进行调整。 考虑使用CSS为图像的父元素提供页面上的空间,并使用 sizes 属性来匹配任何媒体查询断点。 您还可以使用 fillcontaincover 以及 object-position 来定义图像应该如何占用该空间。

规范化图像:

如果您正在从自己控制的源提供图像,请考虑修改图像流程以将图像规范化到特定大小。

修改API调用:

如果您的应用程序使用API调用(例如到CMS)检索图像URL,则可能可以修改API调用以返回带有URL的图像尺寸。

如果上述方法都不适用于调整图像大小,则 next/image 组件被设计为可以与标准的 <img> 元素一起在页面上很好地工作。

样式

样式化 Image 组件类似于样式化普通的 <img> 元素,但有一些注意事项:

  • 使用 classNamestyle,而不是 styled-jsx

    • 在大多数情况下,我们建议使用 className 属性。这可以是导入的CSS模块、全局样式表等。
    • 您还可以使用 style 属性分配内联样式。
    • 您不能使用 styled-jsx,因为它是范围限定于当前组件的(除非将样式标记为全局)。
  • 使用 fill 时,父元素必须具有 position: relative

    • 这对于以该布局模式正确呈现图像元素是必要的。
  • 使用 fill 时,父元素必须具有 display: block

    • 这是 <div> 元素的默认设置,但在其他情况下应该进行指定。

示例

响应式

responsive image

import Image from 'next/image'
import mountains from '../public/mountains.jpg'

export default function Responsive() {
return (
<div style={{ display: 'flex', flexDirection: 'column' }}>
<Image
alt="Mountains"
// 导入图像将自动设置宽度和高度
src={mountains}
sizes="100vw"
// 使图像显示全宽度
style={{
width: '100%',
height: 'auto',
}}
/>
</div>
)
}

填充容器

fill container

import Image from 'next/image'
import mountains from '../public/mountains.jpg'

export default function Fill() {
return (
<div
style={{
display: 'grid',
gridGap: '8px',
gridTemplateColumns: 'repeat(auto-fit, minmax(400px, auto))',
}}
>
<div style={{ position: 'relative', height: '400px' }}>
<Image
alt="Mountains"
src={mountains}
fill
sizes="(min-width: 808px) 50vw, 100vw"
style={{
objectFit: 'cover', // cover, contain, none
}}
/>
</div>
{/* 网格中的更多图像... */}
</div>
)
}

背景图像

background image

import Image from 'next/image'
import mountains from '../public/mountains.jpg'

export default function Background() {
return (
<Image
alt="Mountains"
src={mountains}
placeholder="blur"
quality={100}
fill
sizes="100vw"
style={{
objectFit: 'cover',
}}
/>
)
}

有关使用各种样式的 Image 组件的示例,请参阅 Image 组件演示

其他属性

查看 next/image 组件可用的所有属性

配置

next/image 组件和 Next.js 图像优化 API 可以在 next.config.js 文件中进行配置。 这些配置允许您启用远程图像、定义自定义图像断点、更改缓存行为等。

阅读有关图像配置的完整文档以获取更多信息