把猫咪装进 public/ 文件夹:Next.js 静态资源管理的魔幻漂流

0. 开场白:为什么 Next.js 给猫咪留了个 VIP 座位?

在 Next.js 的王国里,页面是王子,API 是骑士,而 public/ 就是皇家动物园

所有不会说话(不会编译)的小可爱------图片、字体、音频、甚至你偷偷塞进去的 robots.txt------

都能在这里免门票、零安检、光速直达浏览器


1. public/ 的底层身份:一个"零打包"时空隧道

1.1 打包流水线中的"逃票口"

Next.js 的构建流程像一条精密的寿司传送带

  1. /pages → 被 Webpack 切片、压缩、加哈希
  2. /api → 被 Babel 嚼碎成 Node 可吞咽的形状
  3. /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 的皇家动物园。

相关推荐
LFly_ice36 分钟前
学习React-9-useSyncExternalStore
javascript·学习·react.js
gnip1 小时前
js上下文
前端·javascript
中草药z1 小时前
【Stream API】高效简化集合处理
java·前端·javascript·stream·parallelstream·并行流
不知名raver(学python版)1 小时前
npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR!
前端·npm·node.js
醉方休2 小时前
React中使用DDD(领域驱动设计)
前端·react.js·前端框架
excel2 小时前
📖 小说网站的预导航实战:link 预加载 + fetch + 前进后退全支持
前端
学习3人组2 小时前
React 样式隔离核心方法和最佳实践
前端·react.js·前端框架
世伟爱吗喽2 小时前
threejs入门学习日记
前端·javascript·three.js
朝阳5812 小时前
用 Rust + Actix-Web 打造“Hello, WebSocket!”——从握手到回声,只需 50 行代码
前端·websocket·rust