Next.js 14添加Middleware后Public目录图片加载失败求助
问题修复:静态资源请求返回HTML异常
问题背景
原本代码运行正常,添加Middleware文件后出现异常:请求资源/public/icons/handshake_icon.png返回text/html; charset=utf-8,导致资源无效。
相关代码
src/middleware.ts
import { NextRequest, NextResponse } from 'next/server' export const config = { matcher: [ /* * Match all request paths except for the ones starting with: * - api (API routes) * - _next/static (static files) * - _next/image (image optimization files) * - favicon.ico (favicon file) */ '/((?!api|_next/static|_next/image|favicon.ico).*)', ], } export default async function middleware(req: NextRequest) { const url = req.nextUrl // Get hostname of request (e.g. demo.vercel.pub, demo.localhost:3000) let hostname = req.headers .get('host')! .replace('.localhost:3000', `.${process.env.NEXT_PUBLIC_ROOT_DOMAIN}`) const searchParams = req.nextUrl.searchParams.toString() // Get the pathname of the request (e.g. /, /about, /blog/first-post) const path = `${url.pathname}${ searchParams.length > 0 ? `?${searchParams}` : '' }` // rewrites for app pages if (hostname == `help.${process.env.NEXT_PUBLIC_ROOT_DOMAIN}`) { return NextResponse.rewrite( new URL(`/help${path === '' ? '' : path}`, req.url), ) } // rewrite root application to `/` folder if ( hostname === 'localhost:3000' || hostname === process.env.NEXT_PUBLIC_ROOT_DOMAIN ) { return NextResponse.rewrite(new URL(`${path === '/' ? '' : path}`, req.url)) } }
src/app/help/component/Topic.tsx
import Image from 'next/image' import React from 'react' const Topic = () => { return ( <div className="relative w-12 h-12 bg-slate-50"> <Image src={'/public/icons/handshake_icon.png'} alt={props.topicName} fill={true} /> </div> ) } export default Topic
问题原因及修复方案
1. Image组件路径错误
Next.js的public目录是静态资源的根目录,引用资源时不需要添加/public前缀。当前路径/public/icons/handshake_icon.png会被Middleware拦截并重写,返回HTML内容而非静态图片。
修复:
修改Image组件的src属性,去掉/public前缀:
<Image src={'/icons/handshake_icon.png'} alt="握手图标" // 或补充props.topicName的定义 fill={true} />
2. Middleware规则未排除静态资源路径
当前Middleware的matcher规则没有排除/public开头的路径,导致所有静态资源请求都被Middleware处理,触发重写逻辑返回HTML。
修复:
更新middleware.ts中的config.matcher,添加public到排除列表:
export const config = { matcher: [ '/((?!api|_next/static|_next/image|favicon.ico|public).*)', ], }
额外注意
组件中props.topicName未定义,建议补充组件的props参数,避免运行时错误:
interface TopicProps { topicName: string } const Topic = ({ topicName }: TopicProps) => { return ( <div className="relative w-12 h-12 bg-slate-50"> <Image src={'/icons/handshake_icon.png'} alt={topicName} fill={true} /> </div> ) }
内容的提问来源于stack exchange,提问作者Abel Wondwossen
相关产品推荐
相关产品推荐

