build(mobile): declare App platform compiler to stop build:app false green

`@dcloudio/uni-app-plus` was never declared, so `uni build -p app` silently
fell back to an H5 shell: exit code 0, `DONE Build complete.`, but the output
was only `index.html` (still carrying the `/h5/assets/...` base path) with no
`app-service.js`, `app-renderjs.js` or `manifest.json`. Because
`docs/MOBILE_APP_PACKAGING.md` lists that command as a local verification
step, App platform code was reported as built without ever reaching the App
compiler.

Declare the compiler at the same version as the other `@dcloudio` packages,
guard the version alignment in `tests/app-packaging.test.mjs`, and document
that success is judged by the emitted artifacts, not by the DONE line.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-25 23:56:47 +08:00
co-authored by Claude Opus 5
parent ab3af277c1
commit a3a5cf944e
4 changed files with 129 additions and 1 deletions
+1
View File
@@ -35,6 +35,7 @@ npm --prefix mobile-uni run build:app
- 现有品牌源图仅为 64×64,因此这里生成的是**可用于自定义基座和测试包的派生资产**。正式提交商店前应替换为品牌方提供的高分辨率母版,再重新执行生成和预检。
- `androidPrivacy.json.example` 是**未启用的法务模板**,其中 `__TERMS_URL__` 与 `__PRIVACY_URL__` 必须替换为法务确认的 HTTPS 地址。复制为被 Git 忽略的 `androidPrivacy.json` 后,`npm --prefix mobile-uni run verify:app-release` 才会通过。
- iOS 已按实际功能填写麦克风和照片库用途说明;不申请相机、定位、通讯录、蓝牙或广告追踪权限。
- `build:app` 依赖 `@dcloudio/uni-app-plus`(须与其他 `@dcloudio` 包同版本)。缺少该编译器时命令**不报错**,只静默产出带 `/h5/` 基路径的 H5 空壳,产物里没有 `app-service.js` 与 `app-renderjs.js`,App 平台代码等于从未编译。判定 `build:app` 是否真的成功要看产物中是否存在 `app-service.js`、`app-renderjs.js`、`manifest.json`,不能只看 `DONE Build complete.`。
- App-Plus 当前不启用浏览器 WebRTC 实时对练;界面必须降级为录音后转写,不能将该路径宣传为实时语音通话。
- 真机步骤和证据口径见 `docs/MOBILE_APP_DEVICE_ACCEPTANCE.md`。资源预检通过不等于 Android/iOS 真机或应用商店验收通过。
+113 -1
View File
@@ -9,6 +9,7 @@
"version": "0.1.0",
"dependencies": {
"@dcloudio/uni-app": "3.0.0-alpha-5020120260710001",
"@dcloudio/uni-app-plus": "3.0.0-alpha-5020120260710001",
"@dcloudio/uni-h5": "3.0.0-alpha-5020120260710001",
"@dcloudio/uni-ui": "^1.5.12",
"lxgw-wenkai-tc-webfont": "^1.0.0",
@@ -1933,6 +1934,103 @@
"@dcloudio/types": "3.4.31"
}
},
"node_modules/@dcloudio/uni-app-plus": {
"version": "3.0.0-alpha-5020120260710001",
"resolved": "https://registry.npmmirror.com/@dcloudio/uni-app-plus/-/uni-app-plus-3.0.0-alpha-5020120260710001.tgz",
"integrity": "sha512-bYAMi9YqUH6/xGIf/KMlOPQAtLgYmXGCFtw9ZIUGKF4FMrYC/oeSYVJ/WhutgqVuvJau4BoSg/HGIWcqoz1QRA==",
"license": "Apache-2.0",
"dependencies": {
"@dcloudio/uni-app-uts": "3.0.0-alpha-5020120260710001",
"@dcloudio/uni-app-vite": "3.0.0-alpha-5020120260710001",
"@dcloudio/uni-app-vue": "3.0.0-alpha-5020120260710001",
"debug": "4.3.7",
"fs-extra": "10.1.0",
"licia": "1.41.1",
"postcss-selector-parser": "6.1.2"
}
},
"node_modules/@dcloudio/uni-app-uts": {
"version": "3.0.0-alpha-5020120260710001",
"resolved": "https://registry.npmmirror.com/@dcloudio/uni-app-uts/-/uni-app-uts-3.0.0-alpha-5020120260710001.tgz",
"integrity": "sha512-ajHJurf9oaVtMb7W31ACia96QDp87X2HO+V+XRzW9bnI8Oci6UkzJVoFGXTFWQ8J6ecSbdMkz2dtiHdLgqv22g==",
"license": "Apache-2.0",
"dependencies": {
"@babel/parser": "7.25.6",
"@babel/types": "7.25.6",
"@dcloudio/uni-cli-shared": "3.0.0-alpha-5020120260710001",
"@dcloudio/uni-console": "3.0.0-alpha-5020120260710001",
"@dcloudio/uni-i18n": "3.0.0-alpha-5020120260710001",
"@dcloudio/uni-nvue-styler": "3.0.0-alpha-5020120260710001",
"@dcloudio/uni-shared": "3.0.0-alpha-5020120260710001",
"@jridgewell/gen-mapping": "^0.3.3",
"@jridgewell/trace-mapping": "^0.3.19",
"@rollup/pluginutils": "5.1.0",
"@vue/compiler-core": "3.4.21",
"@vue/compiler-dom": "3.4.21",
"@vue/compiler-sfc": "3.4.21",
"@vue/consolidate": "1.0.0",
"@vue/shared": "3.4.21",
"debug": "4.3.7",
"es-module-lexer": "1.5.4",
"estree-walker": "2.0.2",
"fast-glob": "3.3.3",
"fs-extra": "10.1.0",
"magic-string": "0.30.11",
"picocolors": "1.1.0",
"source-map-js": "1.2.1",
"unimport": "4.1.1"
}
},
"node_modules/@dcloudio/uni-app-uts/node_modules/@vue/compiler-core": {
"version": "3.4.21",
"resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.4.21.tgz",
"integrity": "sha512-MjXawxZf2SbZszLPYxaFCjxfibYrzr3eYbKxwpLR9EQN+oaziSu3qKVbwBERj1IFIB8OLUewxB5m/BFzi613og==",
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.23.9",
"@vue/shared": "3.4.21",
"entities": "^4.5.0",
"estree-walker": "^2.0.2",
"source-map-js": "^1.0.2"
}
},
"node_modules/@dcloudio/uni-app-uts/node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/@dcloudio/uni-app-vite": {
"version": "3.0.0-alpha-5020120260710001",
"resolved": "https://registry.npmmirror.com/@dcloudio/uni-app-vite/-/uni-app-vite-3.0.0-alpha-5020120260710001.tgz",
"integrity": "sha512-GBAUNnfhz0ln0KYGx87NcNHGULMr25ZTOBz0YdXl5q3Jggy6YkYe+C0w2P/4xxz3Q2pUVJ4kC0j/twotgfk6Ew==",
"license": "Apache-2.0",
"dependencies": {
"@dcloudio/uni-cli-shared": "3.0.0-alpha-5020120260710001",
"@dcloudio/uni-i18n": "3.0.0-alpha-5020120260710001",
"@dcloudio/uni-nvue-styler": "3.0.0-alpha-5020120260710001",
"@dcloudio/uni-shared": "3.0.0-alpha-5020120260710001",
"@rollup/pluginutils": "5.1.0",
"@vitejs/plugin-vue": "5.2.4",
"@vue/compiler-dom": "3.4.21",
"@vue/compiler-sfc": "3.4.21",
"debug": "4.3.7",
"fs-extra": "10.1.0",
"picocolors": "1.1.0"
}
},
"node_modules/@dcloudio/uni-app-vue": {
"version": "3.0.0-alpha-5020120260710001",
"resolved": "https://registry.npmmirror.com/@dcloudio/uni-app-vue/-/uni-app-vue-3.0.0-alpha-5020120260710001.tgz",
"integrity": "sha512-xOHqxnQ9yJfDIkY0pSQ3bYZBT55HkUVwCfsx8ZhnEVEtcw4FF2GiIo6xk+Ft/sOtmxj9wChOA7mYkIafbN2Qow==",
"license": "Apache-2.0"
},
"node_modules/@dcloudio/uni-cli-shared": {
"version": "3.0.0-alpha-5020120260710001",
"resolved": "https://registry.npmmirror.com/@dcloudio/uni-cli-shared/-/uni-cli-shared-3.0.0-alpha-5020120260710001.tgz",
@@ -3575,7 +3673,6 @@
"version": "5.2.4",
"resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz",
"integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^18.0.0 || >=20.0.0"
@@ -3954,6 +4051,15 @@
"@vue/shared": "3.4.21"
}
},
"node_modules/@vue/consolidate": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/@vue/consolidate/-/consolidate-1.0.0.tgz",
"integrity": "sha512-oTyUE+QHIzLw2PpV14GD/c7EohDyP64xCniWTcqcEmTd699eFqTIwOmtDYjcO1j3QgdXoJEoWv1/cCdLrRoOfg==",
"license": "MIT",
"engines": {
"node": ">= 0.12.0"
}
},
"node_modules/@vue/devtools-api": {
"version": "6.6.4",
"resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz",
@@ -5437,6 +5543,12 @@
"node": ">=8"
}
},
"node_modules/licia": {
"version": "1.41.1",
"resolved": "https://registry.npmmirror.com/licia/-/licia-1.41.1.tgz",
"integrity": "sha512-XqObV8u1KEMdYWaNK0leRrTwhzKnLQEkhbnuUu7qGNH3zJoN7l9sfvF6PfHstSCuUOmpEP+0SBjRrk0I9uZs8g==",
"license": "MIT"
},
"node_modules/lilconfig": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/lilconfig/-/lilconfig-2.1.0.tgz",
+1
View File
@@ -17,6 +17,7 @@
},
"dependencies": {
"@dcloudio/uni-app": "3.0.0-alpha-5020120260710001",
"@dcloudio/uni-app-plus": "3.0.0-alpha-5020120260710001",
"@dcloudio/uni-h5": "3.0.0-alpha-5020120260710001",
"@dcloudio/uni-ui": "^1.5.12",
"lxgw-wenkai-tc-webfont": "^1.0.0",
+14
View File
@@ -1,10 +1,12 @@
import assert from 'node:assert/strict';
import { execFileSync } from 'node:child_process';
import { readFile } from 'node:fs/promises';
import { test } from 'node:test';
import { fileURLToPath } from 'node:url';
import { dirname, resolve } from 'node:path';
const mobileRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
const readJson = async (path) => JSON.parse(await readFile(new URL(path, import.meta.url), 'utf8'));
test('App 图标与启动图映射均可由预检脚本验证', () => {
const output = execFileSync(process.execPath, ['scripts/verify-app-assets.mjs'], {
@@ -13,3 +15,15 @@ test('App 图标与启动图映射均可由预检脚本验证', () => {
});
assert.match(output, /App asset verification passed/);
});
// 缺少 App 平台编译器时 `uni build -p app` 不会报错,只会静默产出带 /h5/ 基路径的
// H5 空壳(无 app-service.js/app-renderjs.js),使 build:app 成为假绿,renderjs
// 实时对练代码实际从未被 App 编译器处理。
test('App 平台编译器已声明且与其他 uni 包同版本,避免 build:app 静默回落 H5', async () => {
const pkg = await readJson('../package.json');
const appPlus = pkg.dependencies?.['@dcloudio/uni-app-plus'];
assert.ok(appPlus, '缺少 @dcloudio/uni-app-plus,build:app 会静默产出 H5 空壳');
assert.equal(appPlus, pkg.dependencies['@dcloudio/uni-app']);
assert.equal(appPlus, pkg.devDependencies['@dcloudio/vite-plugin-uni']);
});