构建流程
说明从打包到产物的完整构建链路
在 项目结构 的最后,我们提到 nuxt.config.ts 负责构建哈希、CDN 前缀与 ISR 缓存规则,package.json 中也包含若干构建相关命令。本节将完整说明这条链路,介绍构建过程及产物内容,便于后续阅读生产部署章节。
开发与生产
日常开发使用 bun run dev,该命令会同时启动前端与 Nitro 服务端,修改代码后立即生效。生产环境则先使用 bun run build 构建,再将产物部署到服务端与 CDN。两者最直观的区别在于构建哈希:开发模式没有构建产物,因此没有版本号,页面底部显示“开发版”,资产位于本地 .nuxt/ 目录;生产构建才会生成真实的构建哈希,JS 与 CSS 也会直接写入产物根目录。此外,bun run generate 会在构建的基础上额外预渲染页面。
构建哈希
生产构建启动时会生成一个构建哈希,由时间戳加 8 位随机字符组成,形如 20260916173000-a1b2c3d4,同一轮构建内保持不变。它有两个用途:一是拼出 CDN 资产目录 static/<hash>/,二是作为站点版本号,经 /api/site 下发给前端,页面底部与后台显示的就是它。
配置 CDN 时,构建产物的引用地址都会带上 static/<hash>/ 前缀。替换发生在构建时:nuxt.config.ts 读取 site.config.ts 中的 cdnUrl,将 Nuxt 的 app.cdnURL 拼接为 CDN 根地址加 static/<hash>,构建出的 JS 与 CSS 均引用该前缀下的地址。生产构建还会去掉默认的 _nuxt/ 层级,因此产物会直接写入 static/<hash>/ 根目录;前文所述“JS 与 CSS 直接落在产物根目录”即指这一行为。不配置 CDN 时不拼接前缀,产物使用站点自身的域名。
构建结束后,哈希会写入 .output/build-hash.json,各部署脚本读这个文件来获知本轮构建的哈希与产物目录。
构建产物
打包:
Bashbun run build完成后产物在 .output/ 下:
目录树.output/
├── public/ 静态资源与构建产物
├── server/ Nitro 服务端
│ └── runtime-assets/ 运行时资产
└── build-hash.json 本轮构建的哈希与 CDN 目录public/ 是站点的静态部分,页面所需的 CSS、JS、字体、favicon 与 manifest.webmanifest 都在里面。server/ 是 Nitro 服务端代码,页面由它在运行时渲染,runtime-assets/ 存放 IP 归属地库、验证码字体这类随包运行的文件。若在 site.config.ts 里开启了 Brotli 压缩,构建时还会为这些文件同时生成 .br 与 .gz 的预压缩版本,在 CDN 或 Nginx 侧可以发送这些压缩文件,节省网络资源。
构建之后
bun run build 结束时,postbuild 会自动执行两条命令:
copy-data.ts:把server/runtime-assets/里的文件复制进产物。Nitro 的构建钩子也会做一次,两处幂等、结果一致。update-sw-cdn.ts:从 Nitro 产物里读回构建哈希,写入.output/build-hash.json。配置了 CDN 时,还会把sw.js里预缓存的资源路径改写成 CDN 地址。favicon 与 imgs、fonts 这些根级资源指向 CDN 根,构建产物指向static/<hash>/;改写完把sw.js与robots.txt复制到server/根目录。
页面缓存
生产环境下,这些页面路由可以配置整页缓存,时长统一 30 分钟:首页、归档、分类、标签、文章、订阅、更新日志、协议、关于、地图、友链、留言、搜索页与 sitemap。
是否启用由 site.config.ts 的 build 区配置的 Redis 决定:配置了 Redis 时页面缓存存进 Redis,发布新内容后最迟 30 分钟内对访客更新;不配置时页面不做整页缓存,每次请求都实时渲染,只有图标会落到文件缓存里。
产物去向
产物有三个去向:
- Node 部署:
.output/整体上传到服务器运行,见 Nodejs 部署。 - Docker 部署:镜像在容器内完成构建,见 Docker 部署。配置了 CDN 时,用
bun run export:bundle把镜像里的public/与build-hash.json导出到dist/<hash>/,整个目录上传到 CDN 的static/下。 - COS:
bun run upload:cos按build-hash.json把构建产物传到 COS 的static/<hash>/。imgs、fonts 这些静态资源目录不在此列,处理方式见 CDN 配置。
部署脚本
构建产物的上传及部署后的运维操作均已整理为脚本,无需手动传输。相关依赖位于 scripts 子包中,主项目安装不包含这部分依赖,首次使用前请先安装:
Bashbun install --cwd scripts各命令的配置都从项目根目录的 .env 读取,完整变量说明见 .env 配置说明。
bun run upload:server:将.output/server上传到服务器。该命令通过 SFTP 连接SERVER_HOST指定的主机,将文件传输至SERVER_UPLOAD_DIR,远程目录不存在时自动创建;端口、用户名与并发数分别由SERVER_PORT、SERVER_USER、SERVER_UPLOAD_CONCURRENCY控制,未填写时默认使用 22、root 和 8。node_modules与runtime-assets两个目录默认不上传,首次部署时加上--node-modules一并传输;如需预览待上传文件,可加--dry-run,此时只列出文件而不连接服务器。bun run upload:cos:将构建产物上传到 COS 的static/<hash>/。该命令从.output/build-hash.json读取本轮构建目录,仅上传 JS、CSS 及其.br、.gz预压缩版本和builds/元数据;sw.js与manifest.webmanifest不在其中,由镜像回源提供。上传前会先清空远端同名目录,脚本列出远端文件并在确认后执行删除与上传。存储桶与密钥由.env中的COS_BUCKET、COS_REGION、COS_SECRET_ID、COS_SECRET_KEY配置。命令后附加public下的子目录名时,仅上传该目录;远端前缀始终取自build-hash.json的dir,文件缺失时脚本直接退出。bun run restart:server:通过宝塔面板的 API 重启 Node 项目,上传完产物后执行一次、新产物即生效,不用打开面板。默认执行重启,把 start 或 stop 作为参数传入就是启动与停止,如bun run restart:server -- start。需要在 .env 配好 BT_PANEL_URL、BT_API_KEY、BT_PROJECT_NAME 三项,并在面板的 API 接口设置里开启接口、把运行脚本的本机公网 IP 加入白名单,否则请求会被拒绝。bun run clear:redis:通过宝塔面板的 API 清空 Redis,页面缓存与搜索缓存随之全部失效、访问时重建。配置与上一条相同,清空的范围是 Redis 的全部数据库。bun run export:bundle:Docker 部署专用。镜像构建完成后,把镜像里的public/与build-hash.json导出到dist/<hash>/。它起一个临时容器拷出文件,不影响正在运行的服务,整个目录上传到 CDN 的static/下即可。镜像名默认 imqi1-cms:latest、导出位置默认 ./dist,分别可用 IMAGE_NAME 与 DEST_ROOT 环境变量改。