Per Issue #2, the static build workflow now consistently uses: - npm_config_registry env var to switch to npmmirror (China mainland) - duoji-node-modules named volume (replaces --tmpfs to avoid noexec) - duoji-npm-cache named volume (faster subsequent installs) - npm ci --no-audit --no-fund (faster CI/deploy) - caddy reload note: bind mounts require docker-compose up -d caddy - volume cleanup commands (docker volume rm ...)
7.6 KiB
高徳乐 AI 舵机选型助手:静态部署说明
本项目提供纯静态构建方式。产品数据、图片、选型计算、筛选和弹窗交互都在浏览器中运行;网站运行时不需要 Node.js、数据库、API 或 Cloudflare Worker。
当前服务器的推荐方案
服务器已经有 Docker Compose 管理的 Caddy 网关,并且 Caddy 占用 80/443 端口。因此本项目应当:
- 使用
npm run build:static生成dist-static/。 - 将
dist-static/同步到服务器静态目录。 - 把静态目录以只读方式挂载到现有 Caddy 容器。
- 在现有 Caddyfile 中增加
duoji.dbpi.com.cn的站点配置。
不要为本项目另起 Nginx,不要让新容器绑定 80/443,也不要改动现有 galderma-api 和 galderma-db 容器。
给 Git AI 的部署任务
可以直接把下面这段话发给仓库里的 AI:
请把本仓库部署为
duoji.dbpi.com.cn的纯静态网站。不要执行npm run build,不要启动 Vinext Server、Node.js 后端或 Cloudflare Worker;请执行npm run build:static,发布生成的dist-static/目录。服务器已有 Docker Compose 管理的 Caddy 网关,80/443 端口不能抢占,也不要启动独立 Nginx 或新的 80 端口容器。请先检查现有/root/galderma/docker-compose.yml和 Caddyfile,在 Caddy 服务中增加只读挂载/var/www/duoji:/srv/duoji:ro,并增加仓库deploy/Caddyfile.duoji中的站点配置。构建时服务器没有 Node.js,使用一次性node:22-alpine容器构建,并通过环境变量npm_config_registry=https://registry.npmmirror.com切换到中国大陆 npm 镜像(官方源经常连不上);用两个 Docker named volume 分别隔离node_modules(duoji-node-modules,解决tmpfs默认noexec导致 esbuild 执行失败的问题)和 npm 缓存(duoji-npm-cache,加快后续依赖安装)。修改前备份 Caddy 配置,修改后先校验配置,再只重载 Caddy;bind mount 改动必须重启 caddy 容器才生效(caddy reload不会重挂 volume),实际影响约 3 秒。不要改动 galderma-api、galderma-db 和现有站点,不要把密码、SSH 密钥或 token 写入仓库。最后用 curl 检查首页、产品图片和 HTTPS。
构建静态文件
如果服务器有 Node.js:
npm ci --no-audit --no-fund
npm run build:static
如果服务器没有 Node.js,使用一次性 Docker 构建容器。该方式不会在宿主机留下 node_modules,并通过环境变量切换 npm 镜像源以适配中国大陆网络环境:
docker volume create duoji-node-modules
docker volume create duoji-npm-cache
docker run --rm \
-v "$PWD":/src \
-v duoji-node-modules:/src/node_modules \
-v duoji-npm-cache:/root/.npm \
-w /src \
-e npm_config_registry=https://registry.npmmirror.com \
node:22-alpine \
sh -lc 'npm ci --no-audit --no-fund && npm run build:static'
为什么这样设计
npm_config_registry环境变量 而不是npm config set:避免在仓库或容器里写死镜像配置;非中国大陆环境不传这个环境变量就自动走官方源。- named volume
duoji-node-modules替代--tmpfs:tmpfs 默认noexec,会导致 esbuild 的 postinstall 可执行文件无法运行;named volume 既隔离宿主机又支持可执行权限。 - named volume
duoji-npm-cache缓存/root/.npm:第二次及以后的构建会复用缓存,npm ci显著加快(从几十秒降到几秒)。注意:npm ci仍会重建node_modules(不修改 package-lock),加速主要来自缓存元数据;node_modulesvolume 主要用来隔离宿主机并解决执行权限问题。 --no-audit --no-fund:跳过 npm 审计和赞助信息,加快 CI/部署速度。
清理构建缓存
需要彻底清理时执行:
docker volume rm duoji-node-modules
docker volume rm duoji-npm-cache
构建完成后,网站文件位于 dist-static/,入口是 dist-static/index.html。当前静态入口不依赖 app/layout.tsx 的动态 metadata,因此不要用 npm run build 代替 npm run build:static。
与现有 Caddy 共存
1. 同步静态文件
以下路径是示例,实际执行时让部署 AI 先确认服务器目录和权限:
sudo mkdir -p /var/www/duoji
sudo rsync -a --delete dist-static/ /var/www/duoji/
2. 给 Caddy 服务增加只读目录挂载
在现有 Docker Compose 的 Caddy 服务中增加:
volumes:
- /var/www/duoji:/srv/duoji:ro
不要覆盖原有 volumes;只追加这一项。容器内的 /srv/duoji 对应本项目的静态文件目录。
3. 增加 Caddy 站点
将 deploy/Caddyfile.duoji 的内容追加到现有 Caddyfile。配置核心如下:
duoji.dbpi.com.cn {
root * /srv/duoji
encode gzip zstd
try_files {path} /index.html
file_server
}
修改前先备份 Caddyfile,并确认没有同名的 duoji.dbpi.com.cn 配置。修改后先验证:
docker exec galderma-caddy-1 caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile
由于新增了 bind mount /var/www/duoji:/srv/duoji:ro,必须重启 Caddy 容器才会挂载(caddy reload 不会重新挂载 volume),执行:
cd /root/galderma
docker-compose up -d caddy
实际影响约 3 秒,仅重启 Caddy,galderma-api / galderma-db 容器不受影响。如果现有容器内的 Caddyfile 路径不同,以 Docker Compose 的实际挂载路径为准。不要为了部署本项目执行整个 Compose 栈的重建或清理操作。
4. 验证
curl -I https://duoji.dbpi.com.cn/
curl -I https://duoji.dbpi.com.cn/catalog-products/precision-gears/418.jpg
curl -I https://duoji.dbpi.com.cn/catalog-products/precision-gears-size/418.jpg
浏览器中再检查首页、#selector、#products 和 #precision-gears,并打开任意精密齿轮产品确认"产品尺寸"可以切换。
后续更新
首次部署后已经创建了 duoji-node-modules 和 duoji-npm-cache 两个 named volume,后续更新直接复用:
git pull --ff-only origin main
docker run --rm \
-v "$PWD":/src \
-v duoji-node-modules:/src/node_modules \
-v duoji-npm-cache:/root/.npm \
-w /src \
-e npm_config_registry=https://registry.npmmirror.com \
node:22-alpine \
sh -lc 'npm ci --no-audit --no-fund && npm run build:static'
sudo rsync -a --delete dist-static/ /var/www/duoji/
只更新静态文件时不需要重新构建或清理其他业务容器,也不需要重启 Caddy 容器(Caddy 的 file_server 每次请求都会读磁盘,新文件一上来就生效)。仅当 docker-compose.yml 或 Caddyfile 本身有改动时才需要 docker-compose up -d caddy。
其他部署方式
仓库中的 Dockerfile.static 和 deploy/nginx-static.conf 可用于独立服务器或独立容器场景,但不适用于当前已经由 Caddy 占用 80/443 的服务器。当前服务器优先使用"静态文件 + 现有 Caddy"方案。
注意事项
- 静态版的"申请样品"和"联系我们"表单目前只在浏览器中生成演示编号,不会将线索写入 CRM 或数据库。
- 如果后续要保存客户线索,需要另行接入表单 API、企业微信、CRM 或数据库,不要把密钥写进前端代码。
- 页面使用根路径资源,建议部署在域名根路径,不建议直接部署到
/servo/子目录。 - 目前尺寸图仅在产品详情弹窗切换到"产品尺寸"时加载,图片体积主要影响磁盘和用户主动查看尺寸图时的下载,不会首屏一次性加载全部图片。