Menu

图片优化

使用内置的 next/image 组件优化你的图像。

示例

根据 Web Almanac 的数据,图像占典型网站页面大小的很大一部分,并且可能对网站的 LCP 性能产生显著影响。

Next.js Image 组件扩展了 HTML <img> 元素,增加了自动图像优化功能:

  • 尺寸优化: 自动为每个设备提供正确尺寸的图像,使用现代图像格式如 WebP 和 AVIF。
  • 视觉稳定性: 在图像加载时自动防止布局偏移
  • 更快的页面加载: 使用浏览器原生懒加载,图像仅在进入视口时加载,可选择使用模糊占位符。
  • 资源灵活性: 按需调整图像大小,即使是存储在远程服务器上的图像。

🎥 观看: 了解更多关于如何使用 next/imageYouTube (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 必须是静态的,以便在构建时进行分析。

远程图像

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

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

widthheight 属性用于推断图像的正确宽高比,并避免图像加载时的布局偏移。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/**",
      },
    ],
  },
};

了解更多关于 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 web 服务器提供。如果你想直接从 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 文件中进行配置。这些配置允许你启用远程图像定义自定义图像断点更改缓存行为等。

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