锁定原生壳依赖版本门禁

总验收反查移动壳依赖版本检查不可移除

总验收反查桌面壳 Tauri 与 Cargo 版本检查不可移除

同步宿主壳方案文档和项目决策记录
This commit is contained in:
2026-06-21 20:57:38 +08:00
parent 1f4afcdc19
commit 3dfd61f0a0
3 changed files with 56 additions and 0 deletions
@@ -16,6 +16,14 @@
---
## 2026-06-21 原生壳依赖版本门禁不可移除
- 背景:Expo / React Native / Tauri 的依赖版本会影响 WebView、权限、capability、构建产物和宿主桥接行为;两端单端配置检查已经锁定 package、lockfile 和 Cargo 解析版本,但根级总验收也需要防止未来重构时把这些锁版本检查从单端脚本中移除。
- 决策:`npm run check:native-shells` 必须反查移动壳 `check-config.mjs` 继续校验 Expo SDK、React Native、WebView、EAS CLI 和 `package-lock.json` 解析版本;桌面壳 `check-config.mjs` 必须继续校验 Tauri CLI、Cargo manifest、`Cargo.lock` 解析版本和直接依赖关系。升级原生壳底层依赖必须同步更新单端配置检查、锁文件和宿主壳方案文档。
- 影响范围:`scripts/check-native-shells.mjs``apps/mobile-shell/scripts/check-config.mjs``apps/desktop-shell/scripts/check-config.mjs`、原生壳依赖升级流程。
- 验证方式:`npm run check:native-shells``npm run check:encoding``git diff --check`
- 关联文档:`docs/【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md`
## 2026-06-20 移动 HostBridge 消息注入失败边界
- 背景:Expo 移动壳通过 WebView `injectJavaScript` 把 HostBridge response 以及 `app.lifecycle``network.statusChanged``navigation.canGoBack` 等宿主事件回放给 H5;如果 WebView 进程切换、页面卸载或注入同步失败,壳层不能因为响应或事件回灌异常而崩溃。
File diff suppressed because one or more lines are too long
+46
View File
@@ -14,6 +14,14 @@ const developmentWorkflowDocPath =
'docs/project-memory/shared-memory/development-workflow.md';
const decisionLogDocPath = 'docs/project-memory/shared-memory/decision-log.md';
const rootPackageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
const mobileShellConfigCheckSource = fs.readFileSync(
'apps/mobile-shell/scripts/check-config.mjs',
'utf8',
);
const desktopShellConfigCheckSource = fs.readFileSync(
'apps/desktop-shell/scripts/check-config.mjs',
'utf8',
);
const productionShellScanRoots = [
'apps/mobile-shell',
@@ -74,6 +82,44 @@ function assertRootNativeShellCheckScripts() {
}
assertRootNativeShellCheckScripts();
function assertNativeShellDependencyVersionGuardrails() {
for (const snippet of [
"const rootPackageLockPath = new URL('../../../package-lock.json', import.meta.url)",
'function assertPackageDependencyVersion(',
'function assertPackageLockVersion(',
"'@expo/metro-runtime': '^56.0.15'",
"expo: '^56.0.12'",
"'react-native': '^0.86.0'",
"'react-native-webview': '^13.16.1'",
"'eas-cli': '^20.3.0'",
"assertPackageLockVersion('eas-cli', '20.3.0')",
]) {
if (!mobileShellConfigCheckSource.includes(snippet)) {
throw new Error(`mobile shell dependency guardrail drifted: missing ${snippet}`);
}
}
for (const snippet of [
"const rootPackageLockPath = new URL('../../../package-lock.json', import.meta.url)",
"const cargoLockPath = new URL('../src-tauri/Cargo.lock', import.meta.url)",
'function assertPackageDependencyVersion(',
'function assertPackageLockVersion(',
'function assertCargoDependencyLine(',
'function assertCargoLockPackageVersion(',
'function assertCargoLockDirectDependency(',
"'@tauri-apps/cli': '^2.11.2'",
"'@tauri-apps/cli': '2.11.2'",
'tauri = { version = "2.11.2", features = ["tray-icon"] }',
"['tauri', '2.11.2']",
'tauri-plugin-single-instance = { version = "2.4.2", features = ["deep-link"] }',
]) {
if (!desktopShellConfigCheckSource.includes(snippet)) {
throw new Error(`desktop shell dependency guardrail drifted: missing ${snippet}`);
}
}
}
assertNativeShellDependencyVersionGuardrails();
const h5HostBridgeCallChainWrapperFiles = [
'src/hooks/useHostLifecycleActive.ts',
'src/hooks/useHostNavigationCanGoBack.ts',