How to Fix: next/image 报错

2 min read

next/image 报错的根因与修复:为什么图片组件在 Next.js 中突然不可用

这个问题通常不是 next/image 组件本身坏了,而是图片来源、构建配置、静态资源路径或运行环境与 Next.js 图片优化机制 不匹配,最终触发编译报错、运行时报错,或者图片请求直接失败。

Understanding the Root Cause

next/image 和普通的 img 标签不同,它不是简单输出一个图片地址,而是会经过 Next.js Image Optimization 处理。也就是说,Next.js 会在编译或运行阶段检查你的图片来源是否合法、路径是否正确、尺寸信息是否完整。

结合这类问题的典型现象,报错一般集中在以下几类:

  • 图片路径不合法:例如把本地图片写成了错误的相对路径,或者资源并不在 public 目录下。
  • 远程域名未配置:如果 src 是远程图片地址,必须在 next.config.js 中通过 images.domainsimages.remotePatterns 白名单放行。
  • 缺少 width / height:旧写法中,next/image 通常要求明确宽高,除非你使用了特定布局模式。
  • 静态导入方式错误:某些场景下,图片应使用 import 导入,而不是随意拼接字符串路径。
  • 资源服务器不兼容:如果图片来自不支持优化请求的源站,Next.js 的图片优化接口可能返回错误。
  • 版本差异:不同版本的 Next.js 对 Image 组件 配置项、属性命名和行为存在差异。

最关键的一点是:next/image 对图片来源的约束比 img 严格得多。因此项目里“普通 img 能显示,但 next/image 报错”是非常常见的现象。

Step-by-Step Solution

下面按排查优先级给出修复方案。建议你按顺序检查。

1. 先确认图片是本地资源还是远程资源

如果你的图片放在项目本地,推荐放入 public 目录,例如:

public/images/avatar.png

然后这样使用:

import Image from 'next/image'

export default function Page() {
  return (
    <Image
      src="/images/avatar.png"
      alt="avatar"
      width={200}
      height={200}
    />
  )
}

不要把路径写成类似下面这种不稳定的相对路径:

<Image src="../../assets/avatar.png" alt="avatar" width={200} height={200} />

如果图片不在 public 中,而是位于源码目录中,则使用静态导入:

import Image from 'next/image'
import avatar from '../assets/avatar.png'

export default function Page() {
  return <Image src={avatar} alt="avatar" />
}

2. 如果是远程图片,配置 next.config.js

如果你的图片地址来自第三方站点、对象存储、CDN 或接口返回的完整 URL,则必须配置白名单。

推荐使用较新的 remotePatterns

/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'example.com',
        pathname: '/**',
      },
      {
        protocol: 'https',
        hostname: 'img.example-cdn.com',
        pathname: '/**',
      },
    ],
  },
}

module.exports = nextConfig

如果你的项目版本较旧,也可能使用:

/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    domains: ['example.com', 'img.example-cdn.com'],
  },
}

module.exports = nextConfig

修改后务必重启开发服务:

npm run dev

3. 检查是否传入了合法的 width 和 height

很多报错来自于 缺失尺寸参数。标准写法如下:

import Image from 'next/image'

export default function Banner() {
  return (
    <Image
      src="/images/banner.jpg"
      alt="banner"
      width={1200}
      height={600}
    />
  )
}

如果你想做响应式布局,可以配合 sizes 使用,而不是省略必要属性:

import Image from 'next/image'

export default function Hero() {
  return (
    <Image
      src="/images/hero.jpg"
      alt="hero"
      width={1200}
      height={800}
      sizes="100vw"
    />
  )
}

4. 如果图片源不适合优化,临时关闭优化验证

某些测试环境、内网地址或特殊图片服务与 Next.js 默认优化流程不兼容,可以先验证是否是优化链路引发的问题:

import Image from 'next/image'

export default function Test() {
  return (
    <Image
      src="https://example.com/test.png"
      alt="test"
      width={300}
      height={200}
      unoptimized
    />
  )
}

如果加上 unoptimized 后恢复正常,说明问题大概率在 图片优化服务、远程源站响应头、格式兼容性 或白名单配置上。

5. 检查 App Router / Pages Router 下的导入方式

无论你使用的是 App Router 还是 Pages Router,正确导入方式都应是:

import Image from 'next/image'

不要误写成其他路径,也不要和浏览器原生图片组件混用导致属性不匹配。

6. 核对实际图片地址是否能直接访问

如果是远程图片,把图片链接直接复制到浏览器中测试。重点检查:

  • 是否返回 200
  • 是否被鉴权拦截
  • 是否发生了 302/403/404
  • 是否返回的其实不是图片,而是一段 HTML 错误页

如果源站本身不可访问,next/image 自然也无法完成优化。

7. 一份可直接参考的正确配置示例

import Image from 'next/image'

export default function Demo() {
  return (
    <div>
      <h1>Image Demo</h1>

      <Image
        src="/images/local-demo.png"
        alt="local image"
        width={400}
        height={240}
      />

      <Image
        src="https://img.example-cdn.com/demo.png"
        alt="remote image"
        width={400}
        height={240}
      />
    </div>
  )
}
/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'img.example-cdn.com',
        pathname: '/**',
      },
    ],
  },
}

module.exports = nextConfig

Common Edge Cases

  • 开发环境正常,生产环境报错:生产环境可能开启了不同的域名、CDN、反向代理或环境变量,导致图片真实来源和本地不一致。
  • 接口返回的图片 URL 是动态域名:例如测试、预发、正式环境域名不同,这时需要统一纳入 remotePatterns
  • 图片 URL 带签名参数:某些对象存储的临时授权链接虽然能访问,但如果域名没配置,依然会被拦截。
  • 把 background-image 的思路直接套到 next/imageImage 组件 更适合内容图片,不适合所有背景图场景。
  • 路径大小写问题:在 Windows 开发正常,但部署到 Linux 后因文件名大小写不一致导致 404。
  • 使用 basePath 或 assetPrefix:如果项目配置了子路径部署,静态资源引用方式需要同步调整。
  • SVG 特殊处理:某些 SVG 使用 img 或内联方案更合适,尤其在需要脚本、样式或复杂交互时。
  • 旧版属性失效:升级 Next.js 后,历史属性或写法可能已变更,需对照当前版本文档。

FAQ

1. 为什么 img 标签能显示,next/image 却报错?

因为 img 只是直接请求图片,而 next/image 会先进行来源校验和优化处理。只要域名未白名单、路径不规范或尺寸缺失,就可能报错。

2. 远程图片一定要配 next.config.js 吗?

是的,绝大多数情况下必须配置。否则 Next.js 无法确认该远程资源是否允许进入 图片优化管道

3. 加了 unoptimized 就好了,是否可以一直这么用?

可以作为临时绕过方案,但不建议长期滥用。因为这样会失去 自动优化、尺寸裁剪、性能收益。更稳妥的做法是修正远程域名配置或图片源问题。

如果你正在排查这个仓库里的问题,最优先检查的就是:图片 src 的实际值是否为远程地址next.config.js 是否配置 images 白名单、以及 width/height 是否完整。这四项通常就能定位绝大多数 next/image 报错 问题。

进一步参考可查看 Next.js Image 官方文档,以及问题中提供的 复现仓库 进行逐项比对。

Leave a Reply

Your email address will not be published. Required fields are marked *