一、本篇目标
前六篇完成了后端和基础环境:
- 第 1 篇:升级决策
- 第 2 篇:环境准备与数据盘
- 第 3 篇:Redis 7.4 源码编译
- 第 4 篇:Nginx 1.28 源码编译
- 第 5 篇:PostgreSQL 17 源码编译 + pgvector + SQL 转换
- 第 6 篇:JeecgBoot 3.9.5 后端编译部署
后端已经跑在 8080 端口,本篇处理前端:
- Node.js 22 环境搭建
- pnpm 10 安装与前端编译
- Nginx 部署 Vue3 静态资源
- 反向代理后端接口
- SPA history 路由回落
- WebSocket 代理
最终目标:
浏览器打开 http://你的IP -> 看到 JeecgBoot 登录页 登录 admin/123456 -> 进入主界面 刷新任意子路由 -> 不报 404本篇的实战过程中踩了不少坑,尤其是 Node.js 和 pnpm 的版本兼容性,都在下文完整记录。
二、部署架构
JeecgBoot 前后端分离,Nginx 是唯一入口:
浏览器 │ ▼ Nginx :80 ├── / → /usr/local/jeecg/frontend (静态文件) ├── /jeecgboot/ → 127.0.0.1:8080/jeecg-boot/ (API 反向代理) └── /websocket → 127.0.0.1:8080/websocket (WebSocket)三、编译前准备
3.1 修改 .env.production
cd/usr/local/src/JeecgBoot/jeecgboot-vue3cp.env.production .env.production.bak-$(date+%Y%m%d-%H%M%S)sed-i's#^VITE_GLOB_DOMAIN_URL=.*#VITE_GLOB_DOMAIN_URL=http://192.168.1.6/jeecgboot#'.env.productiongrep-E'VITE_GLOB_API_URL|VITE_GLOB_DOMAIN_URL'.env.production期望输出:
VITE_GLOB_API_URL=/jeecgboot VITE_GLOB_DOMAIN_URL=http://192.168.1.6/jeecgboot注意:JeecgBoot 3.9.5 的VITE_GLOB_DOMAIN_URL会在运行时通过_app.config.js注入,换 IP 只需改这个文件,不必重新编译。
3.2 初始环境版本
| 组件 | 版本 |
|---|---|
| Node.js | 20.18.2(系统 rpm 安装) |
| pnpm | 12.3.4 |
| 内存 | 93G |
看起来够用,但后面会证明这两项都不行。
四、编译踩坑全记录
坑 1:Node.js 版本不足导致 rolldown 原生模块缺失
第一次执行pnpm install && pnpm run build,报错:
Error: Cannot find native binding. npm has a bug related to optional dependencies... cause: Error: Cannot find module '@rolldown/binding-linux-x64-gnu'原因:Vite 8 依赖 rolldown,其原生模块要求 Node.js ≥ 20.19 或 ≥ 22.12,而当前是 20.18.2。pnpm 在解析可选依赖时跳过了不兼容的包。
解决:升级 Node.js 到 22.23.3(手动下载官方二进制):
cd/tmpLATEST=v22.23.3curl-fLOhttps://nodejs.org/dist/${LATEST}/node-${LATEST}-linux-x64.tar.xztar-xJfnode-${LATEST}-linux-x64.tar.xzmv/usr/local/node22 /usr/local/node22-bak-22.11.0-$(date+%Y%m%d)mv/tmp/node-${LATEST}-linux-x64 /usr/local/node22exportPATH=/usr/local/node22/bin:$PATHnode-v# v22.23.3坑 2:pnpm 12 的 ERR_PNPM_IGNORED_BUILDS
安装依赖时提示:
Error: ERR_PNPM_IGNORED_BUILDS × installing dependencies ╰─▶ Ignored build scripts: @logicflow/core@2.2.4, @scarf/scarf@1.4.0, core-js@2.6.12, ...解决:批准构建脚本:
pnpmapprove-builds--all或在pnpm-workspace.yaml中配置allowBuilds。
坑 3:pnpm 12 的 minimumReleaseAge 供应链策略
安装依赖时不断报:
Error: ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION × installing dependencies ╰─▶ 4 lockfile entries failed verification: exsolve@1.1.3 was published at 2026-10-03T09:36:58.881Z, within the minimumReleaseAge cutoff ...pnpm 11+ 默认开启minimumReleaseAge(默认 1440 分钟),拒绝安装发布不足 24 小时的包。
解决:在项目根目录的pnpm-workspace.yaml中显式设置minimumReleaseAge: 0:
supportedArchitectures:os:-linuxcpu:-x64libc:-glibcallowBuilds:'@logicflow/core':true'@scarf/scarf':truecore-js:trueesbuild:truevue-demi:trueminimumReleaseAge:0关键:命令行--config.minimumReleaseAge=0和环境变量方式在 pnpm 12 中可能被忽略,必须写进pnpm-workspace.yaml。
坑 4:rolldown binding 始终缺失,降级 pnpm 10 并手动安装
即使 Node 升级到 22.23.3,@rolldown/binding-linux-x64-gnu仍然没有装上。尝试 pnpm 12 多种方式无效,最终降级 pnpm 到 10.34.6:
npminstall-gpnpm@10--registry=https://registry.npmmirror.compnpm-v# 10.34.6然后手动添加 binding 包:
cd/usr/local/src/JeecgBoot/jeecgboot-vue3pnpmadd-D@rolldown/binding-linux-x64-gnu@1.2.12--registry=https://registry.npmmirror.com验证:
ls-lanode_modules/@rolldown/# 应出现 binding-linux-x64-gnu 软链接findnode_modules-name"*.node"-path"*rolldown*"# 找到 rolldown-binding.linux-x64-gnu.node坑 5:cross-env 未找到命令
编译时出现:
sh: 行 1: cross-env: 未找到命令这是因为前面的依赖安装因minimumReleaseAge失败,导致node_modules不完整。解决minimumReleaseAge后,重新执行pnpm install即可恢复。
五、最终编译成功
确保 Node 22.23.3、pnpm 10.34.6,且pnpm-workspace.yaml配置正确后,执行:
cd/usr/local/src/JeecgBoot/jeecgboot-vue3exportPATH=/usr/local/node22/bin:$PATHexportNODE_OPTIONS=--max-old-space-size=8192pnpminstallpnpmrun build编译成功输出类似:
✓ built in 1m 20s Done in 4.4s using pnpm v10.34.6检查产物:
du-shdist/# 36Mlsdist/# _app.config.js, assets, index.html, js, ...ls-lhdist/index.html# 17K关键文件_app.config.js内容:
window.__PRODUCTION__JEECGBOOT_PRO__CONF__={..."VITE_GLOB_API_URL":"/jeecgboot","VITE_GLOB_DOMAIN_URL":"http://192.168.1.6/jeecgboot",...}六、部署到 Nginx
6.1 拷贝静态文件
mkdir-p/usr/local/jeecg/frontendrm-rf/usr/local/jeecg/frontend/*cp-rf/usr/local/src/JeecgBoot/jeecgboot-vue3/dist/* /usr/local/jeecg/frontend/chown-Rjeecg:jeecg /usr/local/jeecg/frontendchmod-R755/usr/local/jeecg/frontendchmod-Ro+rX /usr/local/jeecg/frontend# 确保 nginx worker 可读6.2 配置 Nginx vhost
创建/usr/local/nginx/conf/vhost/jeecg.conf:
server { listen 80; server_name 192.168.1.6 localhost; root /usr/local/jeecg/frontend; index index.html; access_log /data/logs/nginx/jeecg-access.log; error_log /data/logs/nginx/jeecg-error.log; location = /sw.js { add_header Cache-Control "no-store, no-cache, must-revalidate"; } location = /manifest.webmanifest { add_header Cache-Control "no-store, no-cache, must-revalidate"; } location = /_app.config.js { add_header Cache-Control "no-store, no-cache, must-revalidate"; } location ~* \.(?:js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ { expires 30d; add_header Cache-Control "public, immutable"; } location / { try_files $uri $uri/ /index.html; } location /jeecgboot/ { proxy_pass http://127.0.0.1:8080/jeecg-boot/; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_connect_timeout 60s; proxy_read_timeout 300s; proxy_send_timeout 300s; } location /websocket { proxy_pass http://127.0.0.1:8080/websocket; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_read_timeout 3600s; proxy_send_timeout 3600s; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }在/usr/local/nginx/conf/nginx.conf的http块中补充:
map $http_upgrade $connection_upgrade { default upgrade; '' close; } include /usr/local/nginx/conf/vhost/*.conf;6.3 日志目录与重载
mkdir-p/data/logs/nginxchown-Rnginx:nginx /data/logs/nginx /usr/local/nginx/sbin/nginx-tsystemctl reload nginx七、验证
curl-sIhttp://192.168.1.6/|head-3curl-sIhttp://192.168.1.6/_app.config.js|head-3curl-sIhttp://192.168.1.6/jeecgboot/sys/randomImage|head-3全部返回 200。浏览器访问http://192.168.1.6,使用 admin / 123456 登录成功。
八、遗留问题:界面显示为 3.8 风格
登录后界面仍是旧版风格,初步判断是主题配置未生效。
JeecgBoot 3.9.5 支持多种菜单风格,可在src/settings/projectSetting.ts中修改menuType,然后重新编译。
此问题将在后续文章中解决。
九、总结
本次前端部署主要耗时在 Node.js 和 pnpm 的版本兼容性上,核心踩坑点:
| 坑 | 关键 | 解决 |
|---|---|---|
| rolldown 原生模块缺失 | Node ≥ 20.19 / 22.12 | 升级到 Node 22.23.3 |
| ERR_PNPM_IGNORED_BUILDS | pnpm 12 策略 | pnpm approve-builds --all |
| ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION | pnpm 11+ 默认 1440 分钟 | pnpm-workspace.yaml写minimumReleaseAge: 0 |
| binding 包缺失 | pnpm 12 可选依赖解析 bug | 降级到 pnpm 10.34.6 + 手动 add |
| cross-env 找不到 | 依赖装不全 | 修复 minimumReleaseAge 后重装 |
Nginx 配置要点:
- SPA 路由回落:
try_files $uri $uri/ /index.html _app.config.js不缓存:Cache-Control: no-store- WebSocket 需要
map $http_upgrade $connection_upgrade - 静态资源长缓存:
expires 30d
最终一键编译命令:
exportPATH=/usr/local/node22/bin:$PATHexportNODE_OPTIONS=--max-old-space-size=8192cd/usr/local/src/JeecgBoot/jeecgboot-vue3pnpminstallpnpmrun build下一篇:部署归档与一键恢复。
项目地址:
- JeecgBoot PostgreSQL 工具链:https://gitee.com/dboru/jeecgboot-pg-tools
- SQL 转换工具:https://gitee.com/dboru/jeecgboot-pg-converter
本系列文章:
- 第 1 篇:为什么从 3.8.3 升级到 3.9.5
- 第 2 篇:环境准备与数据盘规划
- 第 3 篇:Redis 7.4 源码编译与内核参数调优
- 第 4 篇:Nginx 1.28 源码编译与反向代理配置
- 第 5 篇:PostgreSQL 17 源码编译 + pgvector + SQL 转换
- 第 6 篇:JeecgBoot 3.9.5 后端编译部署
- 第 7 篇:JeecgBoot 3.9.5 前端编译部署(本文)
配套文章:
- JeecgBoot 3.9.5 MySQL 脚本一键转 PostgreSQL 完整方案