图片优化

示例

根据 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="作者照片"
      // width={500} 自动提供
      // height={500} 自动提供
      // blurDataURL="data:..." 自动提供
      // placeholder="blur" // 可选的加载模糊效果
    />
  )
}

警告:不支持动态的 await import()require()import 必须是静态的,以便在构建时分析。

您可以在 next.config.js 中配置 localPatterns 来允许特定图片并阻止其他所有图片。

next.config.js
module.exports = {
  images: {
    localPatterns: [
      {
        pathname: '/assets/images/**',
        search: '',
      },
    ],
  },
}

远程图片

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

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

widthheight 属性用于推断图片的正确宽高比,避免图片加载时的布局偏移。这些值并不决定图片文件的渲染尺寸。了解更多关于图片尺寸

app/page.js
import Image from 'next/image'

export default function Page() {
  return (
    <Image
      src="https://s3.amazonaws.com/my-bucket/profile.png"
      alt="作者照片"
      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/**',
        search: '',
      },
    ],
  },
}

了解更多关于 remotePatterns 配置。如果想为图片 src 使用相对 URL,请使用 loader

域名

有时您可能想优化远程图片,但仍使用内置的 Next.js 图片优化 API。为此,保持 loader 为默认设置,并为 Image 组件的 src 属性输入绝对 URL。

为了保护应用免受恶意用户攻击,您必须定义要与 next/image 组件一起使用的远程主机名列表。

了解更多关于 remotePatterns 配置。

加载器

注意在前面的例子中,为本地图片提供了部分 URL ("/me.png")。这得益于加载器架构。

加载器是一个为图片生成 URL 的函数。它修改提供的 src,并生成多个 URL 来请求不同尺寸的图片。这些 URL 用于自动生成 srcset,以便为访问者提供适合其视口大小的图片。

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

您可以通过 loader 属性为单个图片定义加载器,或通过 loaderFile 配置在应用级别定义。

优先级

您应该为每个页面的 最大内容绘制 (LCP) 元素 图片添加 priority 属性。这样做可以让 Next.js 特别优先加载该图片(例如通过预加载标签或优先级提示),从而显著提升 LCP。

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

识别出 LCP 图片后,可以像这样添加属性:

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

export default function Page() {
  return <Image src={profilePic} alt="作者照片" priority />
}

next/image 组件文档 中查看更多关于优先级的信息。

图片尺寸

图片最常损害性能的方式之一是通过_布局偏移_,即图片加载时将页面上的其他元素推开。这个性能问题对用户非常烦人,以至于它有自己的核心 Web 指标,称为 累积布局偏移。避免基于图片的布局偏移的方法是 始终指定图片尺寸。这允许浏览器在图片加载前精确预留足够的空间。

因为 next/image 旨在保证良好的性能结果,所以不能以会导致布局偏移的方式使用,并且必须通过以下三种方式之一指定尺寸:

  1. 使用 静态导入 自动确定
  2. 显式地包含 widthheight 属性
  3. 隐式地使用 fill 使图片扩展以填充其父元素

如果我不知道图片尺寸怎么办?

如果您从不知道图片尺寸的来源访问图片,可以采取以下措施:

使用 fill

fill 属性允许图片由其父元素决定尺寸。考虑使用 CSS 为图片的父元素在页面上留出空间,并使用 sizes 属性匹配任何媒体查询断点。您还可以将 object-fitfillcontaincover 一起使用,以及使用 object-position 定义图片应如何占据该空间。

标准化图片

如果您从控制来源提供图片,考虑修改图片处理流程以将图片标准化为特定尺寸。

修改 API 调用

如果您的应用通过 API 调用(如 CMS)检索图片 URL,您可以修改 API 调用以返回图片尺寸和 URL。

如果以上方法都不适用于确定图片尺寸,next/image 组件设计为可以与标准 <img> 元素一起在页面上良好工作。

样式

为 Image 组件设置样式与为普通 <img> 元素设置样式类似,但有一些准则需要记住:

  • 使用 classNamestyle,而不是 styled-jsx
    • 在大多数情况下,我们推荐使用 className 属性。可以是导入的 CSS 模块全局样式表
    • 也可以使用 style 属性分配内联样式
    • 不能使用 styled-jsx,因为它的作用域限于当前组件(除非将样式标记为 global
  • 使用 fill 时,父元素必须有 position: relative
    • 这是在此布局模式下正确渲染图片元素所必需的
  • 使用 fill 时,父元素必须有 display: block
    • 这是 <div> 元素的默认值,但其他情况下应明确指定

示例

响应式

填充父容器宽度和高度的响应式图片
import Image from 'next/image'
import mountains from '../public/mountains.jpg'

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

填充容器

填充父容器宽度的图片网格
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="山脉"
          src={mountains}
          fill
          sizes="(min-width: 808px) 50vw, 100vw"
          style={{
            objectFit: 'cover', // cover, contain, none
          }}
        />
      </div>
      {/* 网格中的更多图片... */}
    </div>
  )
}

背景图片

占据页面全宽和全高的背景图片
import Image from 'next/image'
import mountains from '../public/mountains.jpg'

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

要查看 Image 组件与各种样式一起使用的示例,请参阅 Image 组件演示

其他属性

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

配置

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

阅读完整的图片配置文档了解更多信息。

On this page