0. 开场白:为什么 Next.js 给猫咪留了个 VIP 座位?
在 Next.js 的王国里,页面是王子,API 是骑士,而 public/
就是皇家动物园 。
所有不会说话(不会编译)的小可爱------图片、字体、音频、甚至你偷偷塞进去的 robots.txt
------
都能在这里免门票、零安检、光速直达浏览器。
1. public/ 的底层身份:一个"零打包"时空隧道
1.1 打包流水线中的"逃票口"
Next.js 的构建流程像一条精密的寿司传送带:
/pages
→ 被 Webpack 切片、压缩、加哈希/api
→ 被 Babel 嚼碎成 Node 可吞咽的形状/public
→ **没人碰!**直接原封不动复制到.next/static/media
(开发时则映射到/_next
)
就像你把一杯冰美式直接塞给传送带尽头的顾客,跳过厨房、跳过厨师,连拉花都不改。
1.2 物理路径 vs URL:量子纠缠
磁盘路径 | 线上 URL(Dev) | 线上 URL(Prod) |
---|---|---|
public/cat.png |
http://localhost:3000/cat.png |
https://your.vercel.app/cat.png |
public/fonts/maobi.woff2 |
/_next/static/media/maobi.woff2 (被复制) |
同上 |
文件在磁盘上睡觉,URL 在浏览器里蹦迪------薛定谔的映射。
2. 开发体验:把大象放进冰箱只需 3 步
2.1 第一步:开门(放文件)
bash
mkdir public
echo "meow" > public/cat.txt
2.2 第二步:把大象塞进去(代码引用)
js
// pages/index.js
export default function Home() {
return (
<main>
{/* 直接写绝对路径,Next.js 会自动补全 */}
<img src="/cat.png" alt="一只拒绝打包的猫" />
{/* 也可以引用音频 */}
<audio controls src="/meow.mp3" />
{/* 甚至 JSON */}
<script src="/config.json" type="application/json" />
</main>
);
}
注意:路径以
/
开头,就像你告诉浏览器:"去根目录的皇家动物园找!"
2.3 第三步:关门(启动)
bash
npm run dev
# 浏览器会自动打开 http://localhost:3000/cat.png
3. 高阶魔法:让字体和 CSP 一起跳探戈
3.1 字体跨域?不存在的
把 maobi.woff2
扔进 public/fonts/
,在 next.config.js
里加一行:
js
module.exports = {
async headers() {
return [
{
source: '/fonts/(.*)',
headers: [
{ key: 'Access-Control-Allow-Origin', value: '*' }
]
}
];
}
};
浏览器:谢谢,不用带护照了。
3.2 CSP 白名单:给猫咪发门禁卡
js
// next.config.js
module.exports = {
async headers() {
return [
{
source: '/(.*)',
headers: [
{
key: 'Content-Security-Policy',
value: `default-src 'self'; img-src 'self' data:; font-src 'self' /fonts/`
}
]
}
];
}
};
黑客:门没锁,但猫有保镖。
4. 性能玄学:让猫咪坐上 CDN 的火箭
4.1 自动优化:Next.js 的"偷图贼"
- 把
cat.png
扔进public/
→ 无优化 - 把
cat.png
扔进import cat from '../public/cat.png'
→ 自动压缩、WebP、懒加载
结论:想偷懒?放 public。想极致?让 webpack 帮你瘦身。
4.2 CDN 的"瞬移术"
Vercel 会把 public/
直接推到全球边缘节点,TTL=1年 ,
就像把猫咪的写真寄存在全世界的猫咖。
5. 暗黑料理:用 public/ 做"假 API"
5.1 静态 JSON 伪装后端
json
// public/api/v1/users.json
[
{ "id": 1, "name": "喵霸", "role": "CEO (Chief Eating Officer)" },
{ "id": 2, "name": "汪仔", "role": "前端背锅侠" }
]
前端直接 fetch('/api/v1/users.json')
,完全无服务器成本。
后端:我失业了,但 JSON 还在上班。
5.2 404 钓鱼:把错误页也扔进 public
html
<!-- public/404.html -->
<!doctype html>
<title>猫咪走丢了</title>
<img src="/sad-cat.gif" alt="404">
<script>setTimeout(() => location.href='/', 3000)</script>
在 next.config.js
中声明:
js
module.exports = {
trailingSlash: true,
exportPathMap: () => ({
'/404.html': { page: '/404' }
})
};
6. 踩坑指南:当猫咪变成 404
症状 | 诊断 | 处方 |
---|---|---|
GET /cat.png 404 |
文件真没在 public/ |
mv cat.png public/ |
GET /Cat.PNG 404 |
Linux 区分大小写 | 重命名为 cat.png |
GET /cat.png 200 但空白 |
PNG 实际是 SVG | file cat.png 看看 MIME |
GET /cat.png 403 |
CSP 或防盗链 | 检查 img-src 或 nginx 规则 |
7. 彩蛋:把 public/ 变成"元宇宙"入口
7.1 在 public 里放 glTF 模型
html
<!-- public/scene.gltf -->
<a-scene embedded>
<a-entity gltf-model="/scene.gltf"></a-entity>
</a-scene>
浏览器直接访问 https://your.app/scene.gltf
,跳过构建,直抵虚拟世界。
7.2 用 public 做"离线 PWA"缓存
js
// sw.js
self.addEventListener('install', e => {
e.waitUntil(
caches.open('v1').then(c => c.addAll([
'/cat.png',
'/offline.html'
]))
);
});
8. 结语:public/ 是工程师的"任意门"
"把文件扔进 public,就像把信塞进霍格沃茨的猫头鹰邮筒 ------
下一秒,它就能出现在地球另一端。"
------某次 Vercel 部署日志里的神秘备注
下次当你在 public/
里塞下一首 lo-fi 循环的 rain.mp3
,
别忘了给它写个 README:
"致未来的我:如果 404 了,请确认猫还在。"
附录:一键启动脚本(送你的猫薄荷)
bash
npx create-next-app@latest my-cat-app --typescript --tailwind --eslint
cd my-cat-app
mkdir public
curl -L https://placekitten.com/200/300 -o public/cat.png
npm run dev
浏览器打开 http://localhost:3000/cat.png
,
如果看到一只 200×300 的猫,恭喜你------
你已成功把猫咪关进 Next.js 的皇家动物园。