☰
openEuler 24.03 部署 JeecgBoot 3.9.5 前端:pnpm 编译 + Nginx 反向代理实战
2026/10/11 4:33:43 网站建设 项目流程

一、本篇目标

前六篇完成了后端和基础环境:

  • 第 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.js20.18.2(系统 rpm 安装)
pnpm12.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_BUILDSpnpm 12 策略pnpm approve-builds --all
ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATIONpnpm 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 完整方案

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询