首页 / Next.js 16 入门教程 / 图片优化

Next.js 16 入门教程

图片优化

本教程共 42 篇 · 第 17 篇 · 更新于 2026-07-30 · 约 8 分钟阅读

Next.jsNext.js 16 入门教程图片优化next/image性能

17. 图片优化

本节目标:掌握 next/image 组件的核心功能,学会自动优化图片、防止布局偏移、实现懒加载和响应式图片,让页面加载更快、体验更流畅。

为什么需要图片优化?

图片通常是网页中最大的资源。未经优化的图片会导致:

  • 加载缓慢,用户等待时间长
  • 图片加载时页面跳动(布局偏移)
  • 浪费带宽流量
  • 移动端加载大图浪费资源

Next.js 的 <Image> 组件就是为了解决这些问题而生的。它基于原生 <img> 标签扩展,提供了自动优化能力。

核心能力

<Image> 组件提供了四个关键优化:

  1. 尺寸优化:自动为每个设备提供合适尺寸的图片,使用 WebP 等现代格式
  2. 视觉稳定:自动防止图片加载时的布局偏移(CLS)
  3. 更快加载:原生懒加载,图片进入视口才开始加载
  4. 资源灵活:支持按需缩放,包括远程服务器上的图片

本地图片

使用本地图片最简单。把图片放在 public 目录或组件同级目录,然后静态引入:

// app/page.tsx
import Image from 'next/image'
import profile from './profile.png'

export default function Page() {
  return (
    <Image
      src={profile}
      alt="作者头像"
      // width 和 height 会自动提供
      // blurDataURL 也会自动生成
      placeholder="blur" // 加载时显示模糊预览
    />
  )
}
Tip

静态引入图片时,Next.js 会自动获取图片的宽高和生成模糊占位图。你不需要手动指定这些属性。

如果你不想用静态引入,也可以直接指定路径:

import Image from 'next/image'

export default function Page() {
  return (
    <Image
      src="/profile.png"
      alt="作者头像"
      width={500}
      height={500}
    />
  )
}

这种方式需要手动指定 widthheight

远程图片

使用远程图片时,必须手动指定宽高,因为 Next.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.js 默认不允许优化任意远程图片。你需要在 next.config.ts 中配置允许的域名:

// next.config.ts
import type { NextConfig } from 'next'

const config: NextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 's3.amazonaws.com',
        pathname: '/my-bucket/**',
      },
    ],
  },
}

export default config
Note

Next.js 16 写法:remotePatterns 支持通配符 *(匹配单个路径段)和 **(匹配任意数量的路径段)。尽量配置得具体一些,避免安全风险。

fill 模式

当你不知道图片的精确尺寸,或者想让图片自适应容器大小时,可以使用 fill 属性:

export default function Hero() {
  return (
    <div style={{ position: 'relative', width: '100%', height: '400px' }}>
      <Image
        src="/hero.jpg"
        alt="首页大图"
        fill
        style={{ objectFit: 'cover' }}
      />
    </div>
  )
}

使用 fill 时要注意:

  • 父元素必须有 position: relative(或 fixedabsolute
  • 图片默认使用 position: absolute
  • 可以用 objectFit 控制裁剪方式:cover(裁剪填充)或 contain(完整显示)

响应式图片

通过 sizes 属性,你可以告诉浏览器图片在不同屏幕宽度下的显示尺寸。这让 Next.js 生成完整的 srcset,浏览器会自动选择最合适的图片:

import Image from 'next/image'

export default function ResponsiveImage() {
  return (
    <div>
      <Image
        src="/example.png"
        alt="响应式图片示例"
        fill
        sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
        style={{ objectFit: 'cover' }}
      />
    </div>
  )
}

sizes 的含义:

  • 屏幕宽度 ≤ 768px 时,图片占满整个视口宽度
  • 屏幕宽度 ≤ 1200px 时,图片占视口宽度的 50%
  • 更大屏幕时,图片占视口宽度的 33%
Tip

如果不设置 sizes,浏览器会默认图片占满整个视口(100vw),可能导致加载过大的图片。使用 fill 或响应式 CSS 时,务必设置 sizes

占位符效果

图片加载时,<Image> 支持两种占位符:

模糊占位符

静态引入的图片会自动生成模糊占位图:

<Image
  src={profile}
  alt="头像"
  placeholder="blur"
  // blurDataURL 自动生成
/>

对于远程图片,你需要手动提供 blurDataURL

<Image
  src="https://example.com/image.jpg"
  alt="远程图片"
  width={500}
  height={500}
  placeholder="blur"
  blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRg..."
/>

自定义占位符

你也可以使用自定义的 Data URL 作为占位符,比如一个简单的色块或加载动画:

<Image
  src="/image.png"
  alt="图片"
  width={500}
  height={500}
  placeholder="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='100%25' height='100%25' fill='%23f0f0f0'/%3E%3C/svg%3E"
/>

图片质量与格式

质量设置

quality 属性控制图片压缩质量,范围 1-100,默认 75:

<Image
  src="/photo.jpg"
  alt="照片"
  width={800}
  height={600}
  quality={85}
/>
Note

如果原图质量已经很低,提高 quality 值只会增加文件大小,不会改善视觉效果。

格式选择

Next.js 默认使用 WebP 格式。你可以在 next.config.ts 中配置支持的格式:

// next.config.ts
import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  images: {
    formats: ['image/avif', 'image/webp'],
  },
}

export default nextConfig

AVIF 比 WebP 压缩率更高(约小 20%),但编码时间更长。浏览器会通过 Accept 请求头自动选择支持的格式。

预加载首屏图片

对于首屏大图(LCP 元素),可以使用 preload 属性提前加载:

<Image
  src="/hero.jpg"
  alt="首屏大图"
  width={1200}
  height={600}
  preload={true}
/>
Note

Next.js 16 写法:priority 属性已被弃用,改用 preload。旧版写法是 priority={true}。官方建议在大多数情况下使用 loading="eager"fetchPriority="high" 代替 preload

高级配置

自定义 Loader

如果你想用第三方图片优化服务(比如 Cloudinary、Imgix),可以配置自定义 loader:

'use client'

import Image from 'next/image'

const imageLoader = ({ src, width, quality }) => {
  return `https://res.cloudinary.com/demo/image/upload/w_${width},q_${quality || 75}/${src}`
}

export default function Page() {
  return (
    <Image
      loader={imageLoader}
      src="sample.jpg"
      alt="示例图片"
      width={500}
      height={500}
    />
  )
}

也可以在 next.config.ts 中全局配置:

// next.config.ts
import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  images: {
    loader: 'custom',
    loaderFile: './lib/image-loader.js',
  },
}

export default nextConfig

缓存配置

优化后的图片默认缓存 4 小时。你可以调整缓存时间:

// next.config.ts
import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  images: {
    minimumCacheTTL: 2678400, // 31 天
  },
}

export default nextConfig

设备尺寸

默认情况下,Next.js 生成 8 种不同宽度的图片。你可以自定义:

// next.config.ts
import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  images: {
    deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
    imageSizes: [32, 48, 64, 96, 128, 256, 384],
  },
}

export default nextConfig

常见问题

Q: SVG 图片需要优化吗?

不需要。SVG 是矢量格式,可以无损缩放。Next.js 会自动跳过 SVG 的优化。如果你确实想用 <Image> 加载 SVG,建议加上 unoptimized

<Image src="/logo.svg" alt="Logo" width={200} height={50} unoptimized />

Q: 静态导出能用图片优化吗?

静态导出(output: 'export')不支持运行时的图片优化。你需要配置自定义 loader,或者使用外部图片优化服务。

Q: 如何生成深色模式下的不同图片?

可以用 CSS 媒体查询切换显示不同的 <Image> 组件:

import styles from './theme-image.module.css'
import Image from 'next/image'

export default function ThemeImage({ srcLight, srcDark, alt }) {
  return (
    <>
      <Image src={srcLight} alt={alt} className={styles.imgLight} />
      <Image src={srcDark} alt={alt} className={styles.imgDark} />
    </>
  )
}