Repository navigation
Commit 706ac52
perf(console): answer an app page's views, page and dashboard reads from the app bundle first (#28754)
<!-- claude-projects-attribution: {"github_login":"zhuangjianguo"} -->
_Requested by **Steedos** · [project
thread](https://claude.ai/code/project/chan_018ETKaNwMZCNRYD7D8Q9Ubb?thread=cmsg_018ETKaNwMZCNRYD7D8Q9UbbNiiAtyW6uY3eTDyWYkBLff)_
Part of #28645
Clause-②: yes (widening)
Metadata-protocol: none
## 维护者速读
- 改了什么:进入应用后,页面、仪表盘名称和对象视图优先从应用元数据包(bundle)读取;控制台在根部只进入一次
bundle;“对象是否存在”的检查不再拉视图列表。
- 为什么改:这是 #28645 的第一步。读者不再依赖整张 page/dashboard 列表后,下一步(PR
2,#28680)才能去掉导航同步的这两次列表读取。
- 风险与回滚:风险在对象视图的组合,bundle 外的对象仍按 `/meta/view` 列表组合;回滚即还原本 PR,无数据或协议变更。
-
先看:`ui/packages/app-shell/src/providers/MetadataProvider.tsx`(`viewsForObjects`、`peekBundle`)、`ui/packages/app-shell/src/console/appObjectScope.ts`(`enterAppBundle`)、`ui/packages/app-shell/src/views/PageView.tsx`。
- 两分钟验证:`cd ui && pnpm exec vitest run
packages/app-shell/src/providers/__tests__/MetadataProvider.bundleFirstReads-28645.test.tsx`,预期
17 个用例全绿。
- 需要你做的:无,席位落地。
## What changes
The app metadata bundle (#27627) answers by-name reads, but the
console's readers looked names up in whole lists. This PR moves those
readers to the bundle first:
- **`MetadataProvider`** stops reading `/meta/view` at mount
(`EAGER_TYPES = ['app']`). A route's object scope composes each object
the bundle holds with the bundle's views. It reads the `/meta/view` list
only when a name it asks is outside the bundle, and only for the objects
the bundle does not hold. A list already in hand keeps answering while a
bundle loads, so a settled scope never unsettles. The whole registry
(`objects`) still reads the list beside it.
- **Bundle-first by-name reads** (`providers/bundledReads.ts`):
`PageView`, `AppContent`'s page scope, `AppHeader`'s phone title,
`useRecentItemLabel` and `useNavTargetLabel` read a page or dashboard
from the bundle, prefer-local by owner package. A miss falls back to the
list as before.
- **One bundle entry, at the console root**: `useAppObjectScopePrefetch`
enters the app's bundle as soon as the app list names the app.
`AppContent` reuses that entry (`enterAppBundle`) instead of
revalidating it. Leaving the app ends the entry.
- **`useObjectPresence`** asks its object with a package-local `views:
false` and reads no views.
- **`useServedViewItems(read)`**: `AppHeader` reads views only on an
object's view route.
- **`@object-ui/data-objectstack`**: new
`ObjectStackAdapter.peekAppBundle()` and the exported types
`AppBundlePeek`, `AppBundleItems`, `AppBundleEntry`, with TSDoc. This is
the Clause-② widening.
`NavigationSyncEffect` (`useNavigationSync.ts`) is untouched. It still
reads `/meta/page` and `/meta/dashboard`, which PR 2 removes (#28680,
maintainer ruling A).
## Tests
- New `MetadataProvider.bundleFirstReads-28645.test.tsx` (17 cases) and
`appBundlePeek-28645.test.ts` (5 cases). `appObjectScope-12811.test.tsx`
adds the root bundle entry and its reuse through the console's adapter
wrapper.
- Updated pins that relied on the eager view read: `objectScope-12811`,
`namesOnlyScope-12980`, `oneMetadataRead-13044`,
`switchDropsAdapter-13044`, `ConnectedShell.sessionGate`.
- Each new rule was ablated and each one turned its pin red: eager view,
bundle views, `views: false`, the pending-before-enter rule, bundled
objects keeping bundle views, and the root entry.
## Acceptance notes
Measured on a production console build (`pnpm build` + `pnpm
console:build`, `pnpm dev -- --fresh`), `showcase_app`, admin, API calls
of a warm reload, two runs each. Base `2678600d`, head of this PR:
| Route | Base | PR 1 | Difference |
|---|---|---|---|
| `page/showcase_start_here` | 26 | 26 | `/meta/view` −1,
`/api/v1/packages` +1 |
| `dashboard/showcase_ops_dashboard` | 35 | 35 | none |
| `showcase_task` (object list) | 33 | 33 | none |
Expected with PR 2 (NavigationSyncEffect stops reading the lists): page
26 → 24, dashboard 35 → 33. That is `/meta/page` and `/meta/dashboard`
−1 each, plus this PR's view saving on the page route. This PR ships at
net zero because PR 2 needs these readers off the lists.
Deviations:
- **`/api/v1/packages` +1 on the page route.** `PageView` now draws on
the bundle about 250 ms before the page list would land. Its Studio
design gate (`useStudioDesignGate`) therefore asks `/packages` outside
the in-flight window the sidebar's gates share. `packages-io.ts` forbids
a reuse window, so this PR does not add one.
- **The dashboard route keeps `/meta/view`.** It reads the whole object
registry (`objects`), as on main, and the bundle cannot spare that read
without changing the dashboard route's whole-registry rule.
- **The object list route keeps `/meta/view`.** `showcase_task`'s lookup
target `sys_user` is outside the bundle, so its scope reads the list for
the objects the bundle lacks. A reader skips views only where its output
is the same without them (`useObjectPresence`).
- File surface past the first claim: `app-bundle.ts`, the new
`bundledReads.ts`, `appObjectScope.ts` and `useObjectPresence.ts` (claim
amendment 6559809254). `AppContent`'s page route no longer waits for the
page list bucket. `RecordDetailView` is unchanged, because
`usePageAssignment` still reads the page list on record routes.
- A miss falls back to the list read rather than a by-name read, which
keeps prefer-local resolution.
## Verification
<details><summary>Derived gates (35)</summary>
Run at `23fefe55` (the last commit after it only replaces a module
variable in `appObjectScope.ts`; `check-sdui-manifest` re-ran at the
final head, exit 0). `dispatch-gates --ran`: 35 derived, 35 run, 0
NOT-MEASURED.
```
node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0
node scripts/check-adr-0087-registration.mjs --self-test :: exit 0
node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
node scripts/check-empty-changeset.mjs --base origin/main :: exit 0
node scripts/check-empty-changeset.mjs --self-test :: exit 0
node scripts/check-sdui-manifest.mjs :: exit 0
node scripts/check-sdui-manifest.mjs --self-test :: exit 0
node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0
node scripts/release-pending-publish.mjs --self-test :: exit 0
pnpm --dir ui exec vitest run scripts/ :: exit 0
pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0
pnpm check:changeset-gate-self-tests :: exit 0
pnpm check:closed-ceremony-text :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:dispatcher-error-vocabulary :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:engine-double-contract :: exit 0
pnpm check:error-status-conformance :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:pm-changeset-deadline-census :: exit 0
pnpm check:published-files :: exit 0
pnpm check:query-options-erasure :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:skill-identifier-liveness :: exit 0
pnpm check:test-source-alias :: exit 0
pnpm check:tier-file-adoption :: exit 0
pnpm check:type-check-coverage :: exit 0
pnpm check:type-check-debt :: exit 0
pnpm check:undeclared-dep-imports :: exit 0
pnpm check:watch-hint-literal :: exit 0
pnpm check:where-matcher :: exit 0
```
</details>
<details><summary>Tests and type-check</summary>
- 427 test files naming the touched modules (app-shell,
data-objectstack, console), 6 locked batches at `--maxWorkers=2`: 427
passed, 3527 tests. The full app-shell suite (~71 min) is left to CI's
Test UI shards.
- `pnpm turbo run type-check --filter=@object-ui/app-shell
--filter=@object-ui/data-objectstack`: 66/66 tasks, exit 0.
- `node scripts/check-sdui-manifest.mjs`: exit 0.
- Merged `origin/main` at `e735b79e` with no overlap on touched files
and no parallel fix found.
</details>
## Human Minimum
- [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic.
- [x] 2. Every name I added uses the casing for its kind.
- [x] 3. No formatter ran; `pnpm lint` passes. (run as `eslint --quiet`
over the changed ui files: 0 errors; the whole-workspace lint is left to
CI)
- [x] 4. One issue, one branch off an up-to-date `main`, one pull
request.
- [x] 5. A change that publishes carries a changeset, and both
declaration lines are filled in here and in the changeset.
- [x] 6. `packages/spec` touched: its generated artifacts are
regenerated and committed. (not touched)
- [x] 7. No hand edits to `content/docs/references/`,
`packages/*/CHANGELOG.md` or `content/docs/releases/`.
- [x] 8. Title, body and comments are in English. (except the 维护者速读
block the dispatch rules require)
- [x] The *Before Submitting* list in CONTRIBUTING.md is done.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01QsR2jUjXYpqdaAkEWBHbqG
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent e62dcc5 commit 706ac52
21 files changed
Lines changed: 1281 additions & 59 deletions
File tree
- .changeset
- ui/packages
- app-shell/src
- console
- __tests__
- hooks
- layout
- providers
- __tests__
- views
- data-objectstack/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
| 23 | + | |
23 | 24 | | |
24 | 25 | | |
25 | 26 | | |
| |||
67 | 68 | | |
68 | 69 | | |
69 | 70 | | |
70 | | - | |
| 71 | + | |
71 | 72 | | |
72 | 73 | | |
73 | 74 | | |
| |||
318 | 319 | | |
319 | 320 | | |
320 | 321 | | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
321 | 325 | | |
322 | 326 | | |
323 | 327 | | |
| |||
395 | 399 | | |
396 | 400 | | |
397 | 401 | | |
| 402 | + | |
398 | 403 | | |
399 | | - | |
400 | | - | |
401 | | - | |
| 404 | + | |
402 | 405 | | |
403 | 406 | | |
404 | 407 | | |
| |||
456 | 459 | | |
457 | 460 | | |
458 | 461 | | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
459 | 467 | | |
460 | 468 | | |
461 | 469 | | |
| |||
493 | 501 | | |
494 | 502 | | |
495 | 503 | | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
496 | 509 | | |
497 | | - | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
498 | 513 | | |
499 | 514 | | |
500 | 515 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
17 | | - | |
| 17 | + | |
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
21 | 24 | | |
22 | 25 | | |
23 | 26 | | |
| |||
110 | 113 | | |
111 | 114 | | |
112 | 115 | | |
113 | | - | |
| 116 | + | |
114 | 117 | | |
115 | 118 | | |
116 | 119 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
| 23 | + | |
23 | 24 | | |
24 | | - | |
| 25 | + | |
25 | 26 | | |
26 | 27 | | |
27 | 28 | | |
| |||
96 | 97 | | |
97 | 98 | | |
98 | 99 | | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
99 | 132 | | |
100 | 133 | | |
101 | 134 | | |
102 | 135 | | |
103 | | - | |
104 | | - | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
105 | 139 | | |
106 | 140 | | |
107 | 141 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
58 | 58 | | |
59 | 59 | | |
60 | 60 | | |
| 61 | + | |
61 | 62 | | |
62 | | - | |
| 63 | + | |
63 | 64 | | |
64 | 65 | | |
65 | 66 | | |
| |||
437 | 438 | | |
438 | 439 | | |
439 | 440 | | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
440 | 466 | | |
441 | 467 | | |
442 | 468 | | |
443 | | - | |
444 | | - | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
445 | 477 | | |
446 | 478 | | |
447 | 479 | | |
| 480 | + | |
448 | 481 | | |
449 | 482 | | |
450 | | - | |
451 | | - | |
452 | | - | |
| 483 | + | |
| 484 | + | |
| 485 | + | |
| 486 | + | |
| 487 | + | |
| 488 | + | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
453 | 495 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
70 | 70 | | |
71 | 71 | | |
72 | 72 | | |
| 73 | + | |
73 | 74 | | |
74 | 75 | | |
75 | 76 | | |
| |||
139 | 140 | | |
140 | 141 | | |
141 | 142 | | |
| 143 | + | |
142 | 144 | | |
143 | 145 | | |
144 | 146 | | |
| |||
159 | 161 | | |
160 | 162 | | |
161 | 163 | | |
162 | | - | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
163 | 167 | | |
164 | 168 | | |
165 | 169 | | |
| |||
170 | 174 | | |
171 | 175 | | |
172 | 176 | | |
173 | | - | |
| 177 | + | |
174 | 178 | | |
175 | 179 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
107 | 107 | | |
108 | 108 | | |
109 | 109 | | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
110 | 114 | | |
111 | | - | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
112 | 118 | | |
113 | 119 | | |
114 | 120 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
61 | 61 | | |
62 | 62 | | |
63 | 63 | | |
| 64 | + | |
64 | 65 | | |
65 | 66 | | |
66 | 67 | | |
| |||
80 | 81 | | |
81 | 82 | | |
82 | 83 | | |
| 84 | + | |
83 | 85 | | |
84 | 86 | | |
85 | 87 | | |
| |||
102 | 104 | | |
103 | 105 | | |
104 | 106 | | |
105 | | - | |
| 107 | + | |
106 | 108 | | |
107 | 109 | | |
108 | 110 | | |
| |||
115 | 117 | | |
116 | 118 | | |
117 | 119 | | |
118 | | - | |
| 120 | + | |
119 | 121 | | |
120 | 122 | | |
0 commit comments