<Image>(旧版)

示例

从 Next.js 13 开始,next/image 组件进行了重构以提升性能和开发者体验。为了提供向后兼容的升级方案,旧版 next/image 被重命名为 next/legacy/image

查看新版 next/image API 参考文档

对比

next/legacy/image 相比,新版 next/image 组件有以下变化:

  • 移除了 <img> 外层的 <span> 包装,改用 原生计算宽高比
  • 新增对标准 style 属性的支持
    • 移除 layout 属性,改用 styleclassName
    • 移除 objectFit 属性,改用 styleclassName
    • 移除 objectPosition 属性,改用 styleclassName
  • 移除 IntersectionObserver 实现,改用 原生懒加载
    • 移除 lazyBoundary 属性(无原生等效方案)
    • 移除 lazyRoot 属性(无原生等效方案)
  • 移除 loader 配置,改用 loader 属性
  • alt 属性从可选改为必填
  • 修改 onLoadingComplete 回调函数,接收 <img> 元素的引用

必填属性

<Image /> 组件需要以下属性。

src

必须是以下之一:

使用外部 URL 时,必须将其添加到 next.config.jsremotePatterns 中。

width

width 属性可以表示 渲染 宽度或 原始 宽度(像素),具体取决于 layoutsizes 属性。

当使用 layout="intrinsic"layout="fixed" 时,width 表示 渲染 宽度(像素),因此会影响图片显示大小。

当使用 layout="responsive"layout="fill" 时,width 表示 原始 宽度(像素),因此仅影响宽高比。

width 属性是必填的,除非是 静态导入的图片 或使用 layout="fill" 的情况。

height

height 属性可以表示 渲染 高度或 原始 高度(像素),具体取决于 layoutsizes 属性。

当使用 layout="intrinsic"layout="fixed" 时,height 表示 渲染 高度(像素),因此会影响图片显示大小。

当使用 layout="responsive"layout="fill" 时,height 表示 原始 高度(像素),因此仅影响宽高比。

height 属性是必填的,除非是 静态导入的图片 或使用 layout="fill" 的情况。

可选属性

<Image /> 组件除了必填属性外,还接受许多其他属性。本节介绍 Image 组件最常用的属性。更多不常用的属性详见 高级属性 部分。

layout

图片在视口尺寸变化时的布局行为。

layout行为srcSetsizes包含包装元素和尺寸调节器
intrinsic (默认)缩放以适应容器宽度,但不超过图片原始尺寸1x, 2x (基于 imageSizes)N/A
fixed严格按照 widthheight 尺寸显示1x, 2x (基于 imageSizes)N/A
responsive缩放以适应容器宽度640w, 750w, ... 2048w, 3840w (基于 imageSizesdeviceSizes)100vw
fill在 X 和 Y 轴上拉伸以填充容器640w, 750w, ... 2048w, 3840w (基于 imageSizesdeviceSizes)100vw

loader

用于解析 URL 的自定义函数。在 Image 组件上设置 loader 属性会覆盖 next.config.jsimages 部分 定义的默认 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 示例可能对性能指标产生显著影响。如果没有 33vw sizes,从服务器选择的图片宽度会是实际需要的 3 倍。由于文件大小与宽度的平方成正比,没有 sizes 时用户会下载比实际需要大 9 倍的图片。

了解更多关于 srcsetsizes

quality

优化图片的质量,介于 1100 的整数,100 为最佳质量。默认为 75

priority

当为 true 时,图片会被视为高优先级并 预加载。对于使用 priority 的图片,懒加载会自动禁用。

你应该在检测为 最大内容绘制 (LCP) 元素的任何图片上使用 priority 属性。针对不同的视口尺寸,可能有多个优先级图片是合适的。

仅当图片在首屏可见时使用。默认为 false

placeholder

图片加载时使用的占位符。可选值为 blurempty。默认为 empty

当为 blur 时,将使用 blurDataURL 属性作为占位符。如果 src静态导入 的对象且导入的图片是 .jpg.png.webp.avif 格式,则会自动填充 blurDataURL

对于动态图片,你必须提供 blurDataURL 属性。可以使用 Plaiceholder 等工具生成 base64

当为 empty 时,图片加载期间不会有占位符,只有空白空间。

尝试以下示例:

高级属性

在某些情况下,你可能需要更高级的用法。<Image /> 组件可选地接受以下高级属性。

style

允许 传递 CSS 样式 到底层图片元素。

注意所有 layout 模式都会自动应用自己的样式到图片元素,这些自动样式优先于 style 属性。

同时记住,必填的 widthheight 属性可能与你的样式交互。如果使用样式修改图片的 width,必须同时设置 height="auto" 样式,否则图片会变形。

objectFit

定义当使用 layout="fill" 时,图片如何适应其父容器。

此值传递给 src 图片的 object-fit CSS 属性

objectPosition

定义当使用 layout="fill" 时,图片在其父元素中的位置。

此值传递给应用于图片的 object-position CSS 属性

onLoadingComplete

一个回调函数,在图片完全加载且 占位符 被移除后调用。

onLoadingComplete 函数接收一个参数,包含以下属性的对象:

loading

注意:此属性仅用于高级用法。将图片切换为 eager 加载通常会损害性能

我们建议改用 priority 属性,它能正确处理几乎所有用例的急切加载。

图片的加载行为。默认为 lazy

当为 lazy 时,延迟加载图片直到计算距离视口一定距离。

当为 eager 时,立即加载图片。

了解更多

blurDataURL

一个 Data URL,在 src 图片成功加载前用作占位图片。仅在与 placeholder="blur" 结合时生效。

必须是 base64 编码的图片。它会被放大和模糊处理,因此建议使用非常小的图片(10px 或更小)。包含较大的占位图可能损害应用性能。

尝试以下示例:

你也可以 生成纯色 Data URL 来匹配图片。

lazyBoundary

一个字符串(语法类似 margin 属性),用作检测视口与图片交叉并触发懒 加载 的边界框。默认为 "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 时,源图像将按原样提供,不会改变质量、尺寸或格式。默认为 false

import Image from 'next/image'

const UnoptimizedImage = (props) => {
  return <Image {...props} unoptimized />
}

从 Next.js 12.3.0 开始,可以通过更新 next.config.js 配置将此属性应用于所有图像:

next.config.js
module.exports = {
  images: {
    unoptimized: true,
  },
}

其他属性

<Image /> 组件的其他属性将传递给底层的 img 元素,但以下属性除外:

配置选项

远程模式 (Remote Patterns)

为了保护应用免受恶意用户攻击,使用外部图像时需要进行配置。这确保只有来自您账户的外部图像可以通过 Next.js 图像优化 API 提供服务。这些外部图像可以在 next.config.js 文件中通过 remotePatterns 属性配置,如下所示:

next.config.js
module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'example.com',
        port: '',
        pathname: '/account123/**',
      },
    ],
  },
}

须知:上面的示例将确保 next/legacy/imagesrc 属性必须以 https://example.com/account123/ 开头。任何其他协议、主机名、端口或不匹配的路径将返回 400 Bad Request。

以下是 next.config.js 文件中 remotePatterns 属性的另一个示例:

next.config.js
module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: '**.example.com',
      },
    ],
  },
}

须知:上面的示例将确保 next/legacy/imagesrc 属性必须以 https://img1.example.comhttps://me.avatar.example.com 或任意数量的子域名开头。任何其他协议或不匹配的主机名将返回 400 Bad Request。

通配符模式可用于 pathnamehostname,语法如下:

  • * 匹配单个路径段或子域名
  • ** 匹配任意数量的路径段(末尾)或子域名(开头)

** 语法不能在模式中间使用。

域名 (Domains)

警告:为了保护应用免受恶意用户攻击,建议配置严格的 remotePatterns 而非 domains。仅当您拥有该域名下的所有内容时,才使用 domains

remotePatterns 类似,domains 配置可用于提供允许的外部图像主机名列表。

domains 配置不支持通配符模式匹配,也无法限制协议、端口或路径名。

以下是 next.config.js 文件中 domains 属性的示例:

next.config.js
module.exports = {
  images: {
    domains: ['assets.acme.com'],
  },
}

加载器配置 (Loader Configuration)

如果想使用云提供商优化图像而非 Next.js 内置的图像优化 API,可以在 next.config.js 文件中配置 loaderpath 前缀。这样可以使用相对 URL 作为图像的 src,并自动为您的提供商生成正确的绝对 URL。

next.config.js
module.exports = {
  images: {
    loader: 'imgix',
    path: 'https://example.com/myaccount/',
  },
}

内置加载器 (Built-in Loaders)

以下图像优化云提供商已内置支持:

  • 默认:自动适用于 next devnext start 或自定义服务器
  • Vercel:部署到 Vercel 时自动生效,无需配置。了解更多
  • Imgixloader: 'imgix'
  • Cloudinaryloader: 'cloudinary'
  • Akamailoader: 'akamai'
  • 自定义:loader: 'custom',通过实现 next/legacy/image 组件的 loader 属性使用自定义云提供商

如果需要其他提供商,可以在 next/legacy/image 上使用 loader 属性。

使用 output: 'export' 时,图像无法在构建时优化,只能按需优化。要将 next/legacy/imageoutput: 'export' 一起使用,需要使用非默认加载器。了解更多讨论内容。

next/legacy/image 组件的默认加载器使用 squoosh,因为它安装快速且适合开发环境。在生产环境中使用 next start 时,强烈建议通过运行 npm i sharp 在项目目录中安装 sharp。Vercel 部署无需此操作,因为 sharp 会自动安装。

高级配置

以下配置适用于高级用例,通常不需要。如果选择配置以下属性,将覆盖未来更新中对 Next.js 默认值的任何更改。

设备尺寸 (Device Sizes)

如果知道用户的预期设备宽度,可以在 next.config.js 中使用 deviceSizes 属性指定设备宽度断点列表。当 next/legacy/image 组件使用 layout="responsive"layout="fill" 时,这些宽度用于确保为用户设备提供正确的图像。

如果未提供配置,则使用以下默认值。

next.config.js
module.exports = {
  images: {
    deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
  },
}

图像尺寸 (Image Sizes)

可以在 next.config.js 文件中使用 images.imageSizes 属性指定图像宽度列表。这些宽度与设备尺寸 (Device Sizes) 数组拼接,形成用于生成图像 srcset 的完整尺寸数组。

之所以有两个独立的列表,是因为 imageSizes 仅用于提供 sizes 属性的图像,表示图像小于屏幕的完整宽度。因此,imageSizes 中的尺寸应全部小于 deviceSizes 中的最小尺寸。

如果未提供配置,则使用以下默认值。

next.config.js
module.exports = {
  images: {
    imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
  },
}

可接受格式 (Acceptable Formats)

默认的图像优化 API 会通过请求的 Accept 标头自动检测浏览器支持的图像格式。

如果 Accept 标头匹配多个配置的格式,则使用数组中的第一个匹配项。因此,数组顺序很重要。如果没有匹配项(或源图像为动画图像),图像优化 API 将回退到原始图像的格式。

如果未提供配置,则使用以下默认值。

next.config.js
module.exports = {
  images: {
    formats: ['image/webp'],
  },
}

可以通过以下配置启用 AVIF 支持。

next.config.js
module.exports = {
  images: {
    formats: ['image/avif', 'image/webp'],
  },
}

须知:AVIF 编码通常比 WebP 多花 20% 时间,但压缩率比 WebP 高 20%。这意味着首次请求图像时通常较慢,但后续缓存的请求会更快。

缓存行为

以下描述了默认加载器 (loader) 的缓存算法。对于其他加载器,请参考云提供商的文档。

图像在请求时动态优化并存储在 <distDir>/cache/images 目录中。优化后的图像文件将在后续请求中提供服务,直到过期。当请求匹配已缓存但过期的文件时,会立即返回过期的图像。然后在后台重新优化图像(也称为重新验证),并使用新的过期日期保存到缓存中。

可以通过读取 x-nextjs-cache(部署在 Vercel 时为 x-vercel-cache)响应标头的值来确定图像的缓存状态。可能的值如下:

  • MISS - 路径不在缓存中(最多发生一次,在首次访问时)
  • STALE - 路径在缓存中但已超过重新验证时间,因此将在后台更新
  • HIT - 路径在缓存中且未超过重新验证时间

过期时间(或更准确地说,最大存活时间)由 minimumCacheTTL 配置或上游图像的 Cache-Control 标头中的较大者定义。具体来说,使用 Cache-Control 标头的 max-age 值。如果同时找到 s-maxagemax-age,则优先使用 s-maxagemax-age 也会传递给任何下游客户端,包括 CDN 和浏览器。

  • 当上游图像不包含 Cache-Control 标头或值非常低时,可以配置 minimumCacheTTL 以增加缓存持续时间。
  • 可以配置 deviceSizesimageSizes 以减少可能生成的图像总数。
  • 可以配置格式 (formats) 以禁用多种格式,仅使用单一图像格式。

最小缓存 TTL (Minimum Cache TTL)

可以配置缓存优化图像的存活时间(TTL,秒)。在许多情况下,最好使用静态图像导入 (Static Image Import),它会自动哈希文件内容并使用 Cache-Control 标头 immutable 永久缓存图像。

next.config.js
module.exports = {
  images: {
    minimumCacheTTL: 60,
  },
}

优化图像的过期时间(或更准确地说,最大存活时间)由 minimumCacheTTL 或上游图像的 Cache-Control 标头中的较大者定义。

如果需要按图像更改缓存行为,可以配置 headers 在上游图像(例如 /some-asset.jpg,而非 /_next/image 本身)上设置 Cache-Control 标头。

目前没有机制可以手动使缓存失效,因此最好将 minimumCacheTTL 设置为较低值。否则可能需要手动更改 src 属性或删除 <distDir>/cache/images

禁用静态导入 (Disable Static Imports)

默认行为允许导入静态文件,例如 import icon from './icon.png',然后将其传递给 src 属性。

在某些情况下,如果与其他插件冲突(这些插件期望导入行为不同),可能需要禁用此功能。

可以在 next.config.js 中禁用静态图像导入:

next.config.js
module.exports = {
  images: {
    disableStaticImages: true,
  },
}

危险地允许 SVG (Dangerously Allow SVG)

默认的加载器 (loader) 出于几个原因不优化 SVG 图像。首先,SVG 是矢量格式,意味着可以无损调整大小。其次,SVG 具有许多与 HTML/CSS 相同的功能,如果没有适当的内容安全策略 (CSP) 标头,可能导致漏洞。

如果需要使用默认的图像优化 API 提供 SVG 图像,可以在 next.config.js 中设置 dangerouslyAllowSVG

next.config.js
module.exports = {
  images: {
    dangerouslyAllowSVG: true,
    contentDispositionType: 'attachment',
    contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
  },
}

此外,强烈建议同时设置 contentDispositionType 以强制浏览器下载图像,并设置 contentSecurityPolicy 以防止图像中嵌入的脚本执行。

动画图像 (Animated Images)

默认的加载器 (loader) 会自动绕过动画图像的图像优化,并按原样提供图像。

对动画文件的自动检测是尽力而为的,支持 GIF、APNG 和 WebP。如果想显式绕过特定动画图像的图像优化,请使用 unoptimized 属性。

版本历史

版本变更
v13.0.0next/image 重命名为 next/legacy/image