图像优化 3个月前

编程语言
867
图像优化

根据 Web Almanac 的统计,图片占据了典型网站页面大小的很大一部分,并且对你的网站的 LCP 性能有相当大的影响。

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

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

视频教程: 了解更多关于如何使用 next/image → YouTube (9 分钟)

使用方法

import Image from 'next/image'

然后你可以定义图像的 src 属性(可以是本地或远程的图像)。

本地图像

要使用本地图像,请导入你的 .jpg、.png 或 .webp 文件。

Next.js 将根据导入的文件 自动确定 图像的固有宽度和高度。这些值用于确定图像比例,并在图像加载时防止 累积布局偏移

// 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() 不支持。导入必须是静态的,以便在构建时分析。

远程图像

要使用远程图像,src 属性应为 URL 字符串。

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

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

// 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 为默认设置,并为 Imagesrc 属性输入一个绝对 URL。

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

了解更多关于 remotePatterns 配置的信息。

加载器

请注意,在前面的示例中,提供了本地图像的部分 URL(“/me.png”)。这是因为加载器架构的作用。

加载器是一个生成图像 URL 的函数。它修改提供的 src,并生成多个 URL 来请求不同大小的图像。这些多个 URL 被用于自动的 srcset 生成,以便访客在你的网站上获得适合其视口大小的图像。

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

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

优先级

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

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

一旦确定了最大内容渲染图像,你可以这样添加该属性:

// 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 组件文档 中查看更多关于 priority 的信息。

图像尺寸

图像最常影响性能的方式之一是通过布局偏移,即图像加载时将页面上的其他元素推来推去。这种性能问题对用户来说非常烦人,以至于它有一个专门的 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,因为它的作用域仅限于当前组件(除非将样式标记为全局)。
  • 使用 fill 时,父元素必须具有 position: relative
    • 这是在该布局模式下正确渲染图像元素所必需的。
  • 使用 fill 时,父元素必须具有 display: block
    • 这是 <div> 元素的默认设置,但在其他情况下应该指定。

示例

响应式

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="山脉"
        src={mountains}
        sizes="100vw"
        style={{
          width: '100%',
          height: 'auto',
        }}
      />
    </div>
  );
}

填充容器

image

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>
      {/* And more images in the grid... */}
    </div>
  )
}

背景图像

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.config.js 文件 中配置 next/image 组件和 Next.js 图像优化 API。这些配置允许你启用远程图像定义自定义图像断点更改缓存行为等。

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

image
EchoEcho官方
无论前方如何,请不要后悔与我相遇。
1377
发布数
439
关注者
2222970
累计阅读

热门教程文档

C
14小节
Linux
51小节
Djiango
17小节
Rust
84小节
HTML
32小节