开发指南(贡献者)
这一页解决的是改平台代码时最容易反复踩的几件事:
| 你遇到的问题 | 这一页给什么 |
|---|---|
| 命令抄了跑不通(路径是旧名) | 一份逐条核对过的命令清单 |
| 测试"全绿"其实一条没跑 | profile 标签纪律 |
| 改了后端但行为没变 | "改完必须重建 jar"的原因与做法 |
| 前端远程应用构建全绿、浏览器里炸 | 五个守门脚本,谁管哪一类 |
| 提交前不知道要自检什么 | 一份清单 |
只要写应用、不改平台代码,看 插件开发 与
跟着 hello 读源码 就够了 —— 本页针对的是平台侧改动
(wujies-admin / wujies-common-* / wujies-modules/* / 插件加载与市场逻辑)。
三个仓库
没有共同 git 根,各自分支、各自提交、各自推送。改一个功能经常要两边都提交。
| 仓库 | 目录 | 内容 | 当前分支 |
|---|---|---|---|
| 后端 | wujies-platform/ | Java / Spring Boot + 平台 SQL 脚本 | feature/app-market |
| 宿主前端 | plus-ui/ | Vue 3 / Vite,应用市场与远程应用运行时(远程产物落 app-market-dist/) | feature/app-market |
| 插件与打包器 | wujies/wujies-plugins/ | 各应用本体 + 插件前端工程(frontend/<code>-app)+ package.ps1 | master |
wujies-admin在不同位置指不同东西:wujies-platform/wujies-admin/是后端启动模块 (有pom.xml、产物wujies-admin.jar);工作区顶层那个wujies-admin/里 只有app-market-dist/(没有package.json、没有src/)。plus-ui/的package.json里name写的是wujies-admin—— 这是历史遗留, 它指的是宿主前端,不是那个 Java 模块。判据:有vite.config.ts/src/的就是plus-ui/, 凡是指向src/plugins/**、src/views/**的路径都在这里。
分支名以实际仓库配置为准(上表是核对过的当前值),别照抄旧文档里的
my-main / my-ts —— 那两个名字在仓库里已经不存在。
环境与常用命令
本机没有把 JDK / Maven 加进 PATH,所以先设两个变量。下面的命令都在
wujies-platform/ 下执行(它是 Maven 根)。
$env:JAVA_HOME = "C:\Users\<you>\.jdks\corretto-23.0.2" # 目标字节码是 JDK 17
$mvn = "C:\Program Files\JetBrains\IntelliJ IDEA 2025.3.3\plugins\maven\lib\maven3\bin\mvn.cmd"
# 全反应堆编译
& $mvn -B -q compile -DskipTests
# 跑应用市场模块的测试(根 pom 默认 skipTests=true,必须显式打开并指定 profile)
& $mvn -pl wujies-modules/wujies-app-market -B test "-DskipTests=false" "-Dprofiles.active=dev"
# 打可运行 jar(改了后端代码必须做这步才生效)
& $mvn -pl wujies-admin -am -B install -DskipTests
# 启动宿主(手工命令;-D 参数的引号不能省 —— PowerShell 会把 -Dloader.path=x 拆成 /path=x)
java "-Dloader.path=plugins-dist" "-Dspring.profiles.active=dev" -jar "wujies-admin\target\wujies-admin.jar"
# 清残留插件 jar(先加 -DryRun 看它准备删什么)
powershell -NoProfile -ExecutionPolicy Bypass -File script\prune\prune-plugins.ps1 -PluginDir plugins-dist脚本在 script/prune/ 下,却用 $root = Split-Path $PSScriptRoot -Parent 推工程根 ——
推出来是 wujies-platform/script,于是去 script\wujies-admin\target\ 找 jar(那里不存在),
转去打包又因为没有 pom.xml 而失败。同目录的 prune-plugins.ps1 不带 -PluginDir 时
去 script\plugins-dist 找,同样找不到(它会静默打印「目录不存在,无需清理」)。
修好后可以恢复推荐 start-host.ps1(它会把上面的清理与启动串起来)。
推导与完整说明见本地联调。
插件侧(在插件仓库根 wujies/wujies-plugins/ 下执行):
# 只构建某个插件的 jar
& $mvn -pl wujies-hello package -DskipTests
# 打完整应用包(自动构建前后端 + 可选签名),这是发布路径
.\package.ps1 -Plugin wujies-hello -SigningKey keys\private.pem
.\package.ps1 -Keygen # 只生成密钥对,落到 keys\改了后端代码后只跑 mvn compile(哪怕成功)不会重建那个 fat jar,
于是你测的是旧代码,很容易得出「功能没生效」的错误结论,
然后去改本来是对的实现。下结论前先确认 jar 是新的。
⚠️ 两种直觉做法都会骗你:在 fat jar 顶层找 cn/wujies/...class 找不到
(模块类是嵌套在 BOOT-INF/lib/wujies-<模块>.jar 里的,得到的是假阴性);
看嵌套条目的 LastWriteTime 也见过与内部 class 时间不一致。
可靠做法是把嵌套 jar 抽出来看里面那个 class。
maven-compiler-plugin 的增量检查会先清空输出目录再全编,
正在运行、按需懒解析类的 JVM 会抛 NoClassDefFoundError。真实发生过。
测试纪律
根 pom 的 surefire 用 <groups>${profiles.active}</groups> 过滤测试。
没打 @Tag("dev") / @Tag("local") / @Tag("prod") 的测试根本不会被执行。
症状很好认:Tests run 总数没变,但 BUILD SUCCESS —— 看着全绿,其实你的测试没跑。
照抄 wujies-modules/wujies-app-market 下现有测试的写法:三个标签一起打
(例如 PluginMapperRegistrarTest),并且新增后核对一下总数。
| 要点 | 说明 |
|---|---|
只用 -pl <模块> 跑相关模块 | 全反应堆 test 很慢,且和本机环境耦合 |
必须显式 -Dprofiles.active=dev | 它同时是 Spring profile 与 surefire 的 groups 值 |
改了注解 / 常量 / 静态初始化 → 先 clean install | 增量编译按时间戳判"是否需要重编",同一秒内会判定"已是最新" |
| 验证前确认 jar 是新的 | 见上一节 |
前端守门脚本
改了宿主前端或任一远程应用工程之后跑这几条(在 plus-ui/ 下)。它们都是静态检查,
不需要起服务:
| 命令 | 管什么 |
|---|---|
npm run check:remote | 模板组件能否解析三条路 + 白名单名字是否真在宿主 SDK 里 + 已构建产物的 process.env 残留 |
npm run check:globals | 产物里未绑定的自动导入标识符(ESLint no-undef) |
npm run check:runtime | 产物 import 的裸模块名与运行期垫片导出对账 |
npm run audit:menus | C 菜单的 component 能否落到真实页面(按 loadView 的三条路逐条判) |
npm run test:market | 应用市场相关的 vitest 单测(src/plugins/appmarket) |
npm run gen:runtime 生成运行期垫片,已挂在 predev / prebuild:dev / prebuild:prod 上自动执行。
远程产物不进版本库(宿主前端的 .gitignore 里有 app-market-dist/)。
改了 vite.config.ts / 白名单不等于部署里那份 ESM 变了;
单工程构建在插件仓库里执行:pnpm --filter ./frontend/<code>-app run build。
本地联调时产物要让宿主 dev server 能取到 —— 它只从
plus-ui/app-market-dist/remote-apps/ 提供 /remote-apps/**,
所以构建前设 $env:WUJIES_FRONTEND_DIST="<宿主根>\app-market-dist\remote-apps"
(不设就落到工程自己的 dist/,自己看得到、宿主看不到)。
提交前的自检清单
- 新增测试都打了三个 profile 标签,并核对过
Tests run总数 - 改了后端 → 重建过
wujies-admin.jar(mvn -pl wujies-admin -am -B install -DskipTests),且确认 jar 里是新的 class - 改了某个应用 → 用
package.ps1重新打过包,并带了-SigningKey(宿主security.mode=enforce,未签名的包会被拒绝) - 改了前端远程应用 → 重新构建了产物,且五个守门脚本都过
- 动了菜单 →
npm run audit:menus没有新增死菜单 - 动了
migrations/→ 没有修改已执行过的脚本(改了摘要会被拒;要变更就新增脚本,见下) - 改了
.ps1→ 确认仍是 UTF-8 with BOM(编辑工具写完常常把 BOM 丢掉,PS 5.1 会按 ANSI 解析导致中文乱码) - 改了
app.json→ 用无 BOM UTF-8 写(带 BOM 会让 Jackson 解析失败) - 没有把真实凭据、私钥、线上地址提交进仓库
- 一个主题一个 commit(历史里有过 12 个文件混在一个 commit 的情况,回溯很痛苦)
-
git status里没有构建产物:后端仓库的plugins-dist/与插件仓库的target/、keys/都已 gitignore。 两个dist-packages/(平台仓库与插件仓库各一个)都已是历史目录,保留在.gitignore里以防误提交旧二进制; 应用包现在的默认落点在仓库外的<插件仓库的上一级>\.plugin-dist\<appCode>\<版本>\,git 看不到它 —— 所以一旦git status里出现dist-packages/或.plugin-dist/,说明产物被生成到了别处
平台按 script 名比对 checksum,不一致直接报错拒绝执行。
有存量部署时,「把 01-*.sql 里的数据拆出去」这类改动的正确路径是:
先让存量部署跑对应的修复脚本(删掉那几行账本记录),再升级该应用。
迁移脚本只在 install / upgrade 里跑 —— 光把包传上去不会有任何变化。
文档在哪
| 位置 | 内容 | 纳入版本管理 |
|---|---|---|
website/ | 本站(官方文档站与官网) | 是 |
wujies-platform/AGENTS.md | 约束与「已知坑」清单,权威来源,改代码前扫 | 是 |
wujies-platform/docs/ | 平台侧设计与方案文档 | 是 |
wujies/wujies-plugins/docs/ | 人读版开发指南、打包部署教程、AI 操作手册 | 是 |
工作区外层 docs/ | 松散副本与过程记录(含踩坑总记录 开发问题与解决方案.md) | 不在任何仓库里 |
它是三个仓库的共同父目录,本身不是 git 仓库 —— 写进去的东西没人知道、也回溯不了。
要长期保留的内容请放进 wujies-platform/docs/ 或 wujies/wujies-plugins/docs/。
本站的「设计与决策存档」一节列出了这些文档各自什么时候看,见 设计与决策存档。
相关阅读
- 必须遵守的不变量 —— 改代码前扫一遍
- 本地联调 —— 怎么把改动跑起来看效果
- 跟着 hello 读源码 —— 范例应用
wujies-hello的源码索引 - 文档站维护说明 —— 写这一站自己的约定