
next.js 中静态资源(如封面图)必须放在 `public` 目录下才能被直接访问;`app/` 或 `contents/` 等自定义目录中的图片无法通过 url 访问,需通过重定向路径或外部 cdn 方式解决。
在 Next.js(尤其是 App Router)中,只有 public 目录下的文件才会被自动映射为可公开访问的静态资源。你当前将 cover.png 放在 contents/blogpost1/cover.png,该路径属于应用源码结构,而非 Web 可寻址路径——因此 localhost/contents/blogpost1/cover.png 会返回 404。
✅ 正确做法:将封面图移入 public 目录
推荐结构如下:
my-blog/ ├── public/ │ └── covers/ │ ├── blogpost1.png │ └── blogpost2.png ├── app/ │ └── [slug]/ │ └── page.js ├── contents/ │ └── blogpost1/ │ └── index.md // 不再放 cover.png,仅保留 Markdown
然后在 [slug]/page.js 中引用:
// app/[slug]/page.js
export default function BlogPost({ params }) {
const { slug } = params;
// 假设你已通过 fs + gray-matter 解析出 post.data
return (
{post.data.title}
@@##@@
);
}⚠️ 注意:public/covers/ 下的图片需在构建前存在(即 next build 时已就位)。若博客内容动态增删,建议配合 CI/CD 自动同步封面图至 public/covers/。
? 替代方案:使用远程封面图(支持外部域名)
若希望完全解耦图片管理(如从 Unsplash、Cloudinary 或 CMS 获取),可在 Markdown 前置元数据中声明 coverImage 字段:
--- title: "我的第一篇博客" slug: "blogpost1" coverImage: "https://images.unsplash.com/photo-1507003211162-0931c947cce3" --- 正文内容...
接着在 next.config.js 中配置可信图片域名:
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
images: {
domains: ['images.unsplash.com'],
// 如需支持更多来源,追加即可,例如:
// domains: ['images.unsplash.com', 'cdn.example.com']
},
};
module.exports = nextConfig;渲染时直接使用解析后的字段:
@@##@@
✅ 优势:无需手动管理本地文件,支持按需加载、CDN 加速与响应式尺寸(配合 next/image 组件更佳)。
? 总结
| 方案 | 适用场景 | 关键要求 |
|---|---|---|
| 本地 public/ 目录 | 内容稳定、部署可控的静态博客 | 封面图需提前放入 public/covers/,命名与 slug 一致 |
| 远程 coverImage 字段 | 需灵活更新、多端同步或托管在图床的场景 | 配置 next.config.js.images.domains,确保域名可信 |
无论选择哪种方式,请避免在 app/ 或 contents/ 下尝试通过相对路径直接暴露非 public 资源——这是 Next.js 的安全设计,而非 bug。合理利用 public 目录和 next/image 的能力,即可优雅实现高质量封面图加载。











