静态资源
Nuxt 提供两个放静态资源的目录,行为差别很大。选对了能省掉一大堆坏链、体积膨胀、缓存失效的问题。
public/ —— 原样托管
public/ 下的所有内容会以根路径 URL 原样 提供:
public/
├── favicon.ico
├── robots.txt
└── img/
└── hero.png → /img/hero.png
通过绝对路径引用:
<template>
<img src="/img/hero.png" alt="Hero" />
</template>
适合放在 public/ 的:
- favicon、
robots.txt、OG 默认图、sitemap.xml - 需要稳定可预测 URL 的图片
- 与营销 / CDN 配置共用的文件
这里的文件不会带指纹,浏览器可能永远缓存,修改后要改名或手动设置缓存头。
app/assets/ —— 由 Vite 处理
app/assets/ 下的文件会经过 Vite:压缩、打指纹、优化引用。用 ~/ 或 @/ 引用:
<template>
<img src="~/assets/img/hero.png" alt="Hero" />
</template>
适合放在 app/assets/ 的:
- CSS / SCSS / Less 文件
- 需要内联或转换的 SVG
- 需要打指纹与优化的图片
- 随应用打包的字体
这里的文件不会在浏览器里以 /assets/… 访问,Vite 会改写成 /_nuxt/hero-abc123.png 这样的带哈希 URL。
快速对比
| 行为 | public/ |
app/assets/ |
|---|---|---|
| 根 URL 访问 | 是(/foo.png) |
否(被 Vite 改写) |
| 会压缩 / 处理 | 否 | 是 |
| 文件名带指纹 | 否 | 是 |
| 在 Vue 中如何引用 | /img/foo.png |
~/assets/img/foo.png |
| 适合 | 稳定公共 URL | 打包优化后的产物 |
图片进阶:<NuxtImg> 和 <NuxtPicture>
做认真的图片优化建议上 @nuxt/image:
pnpm add -D @nuxt/image
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@nuxt/image'],
image: {
quality: 80,
format: ['webp', 'avif'],
},
})
然后就可以用 <NuxtImg> / <NuxtPicture>:
<template>
<NuxtImg
src="/img/hero.png"
width="1200"
height="630"
loading="lazy"
sizes="sm:100vw md:50vw lg:400px"
/>
</template>
它负责:
- 响应式
srcset - 自动 WebP / AVIF
- 懒加载
- 各种 CDN Provider(Cloudinary、IPX、imgix、Vercel……)
字体
Nuxt 官方有 @nuxt/fonts 模块,能自托管 Google Fonts / 本地字体并避免 CLS:
export default defineNuxtConfig({
modules: ['@nuxt/fonts'],
fonts: {
families: [
{ name: 'Inter', provider: 'google' },
],
},
})
在 CSS 里直接用这个字体名即可,模块会自动注入 @font-face。
想用本地字体?放进 public/fonts/ 然后:
/* app/assets/css/fonts.css */
@font-face {
font-family: 'Display';
src: url('/fonts/display.woff2') format('woff2');
font-display: swap;
}
一句话指南
- 需要稳定的公共 URL? →
public/ - 需要打指纹 / 优化? →
app/assets/ - 大量图片? →
@nuxt/image - 字体? →
@nuxt/fonts或public/fonts/
每类资源只挑一个位置,保持团队一致。