Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

console-starter 的 vite 别名表漏了 5 个源码实际 import 的工作区包,未先构建就 pnpm dev 得到白屏 #3528

Closed

Description

@yinlianghui

越界发现,记录于 #3520(给 examples/console-starter 写 README)期间的实测启动。未在该 PR 中顺手修改;PR #3524 的 README 已把"必须先 pnpm -w build"如实写进"How to run",所以这是打磨类发现,不是今天会挡住按文档操作的读者的缺陷 —— 标 finding,不排队。

现象

examples/console-starter/vite.config.ts 把 24 个 @object-ui/* specifier 别名到 packages/*/src,注释写明用意是让插件的 side-effect 注册命中同一个 ComponentRegistry 单例。但这些 src 文件自己又 import 了 5 个既不在别名表、也不在 examples/console-starter/package.json 里的工作区包:

未覆盖的包 import 它的文件
@object-ui/mobile packages/plugin-list/src/ListView.tsx
@object-ui/providers packages/app-shell/src/views/RecordAttachmentsPanel.tsx
@object-ui/sdui-parser packages/components/src/renderers/layout/page.tsx
@object-ui/plugin-editor packages/app-shell/src/views/metadata-admin/widgets.tsx
@object-ui/react-runtime packages/components/src/renderers/layout/react-page.tsx

这 5 个包只能退回 node 解析,落到 packages/*/dist —— 而 dist 只有构建之后才存在。

实测

在 origin/main 的干净 worktree 里,只 pnpm install(不 pnpm -w build)后 pnpm dev(自选空闲端口 5197):

VITE v8.2.0  ready in 389 ms
(!) Failed to run dependency scan. Skipping dependency pre-bundling. Error: The following dependencies are imported but could not be resolved:
  @object-ui/mobile (imported by .../packages/plugin-list/src/ListView.tsx)
  @object-ui/providers (imported by .../packages/app-shell/src/views/RecordAttachmentsPanel.tsx)
  @object-ui/sdui-parser (imported by .../packages/components/src/renderers/layout/page.tsx)
  @object-ui/plugin-editor (imported by .../packages/app-shell/src/views/metadata-admin/widgets.tsx)
  @object-ui/react-runtime (imported by .../packages/components/src/renderers/layout/react-page.tsx)

src/main.tsx 里 import '@object-ui/plugin-list' 是急切的,而 plugin-list/src/index.tsx 又急切 import { ListView } from './ListView',所以这条链一定会被浏览器走到:

$ curl -s -o /dev/null -w "%{http_code}" http://localhost:5197/@fs/.../packages/plugin-list/src/ListView.tsx
500   → Failed to resolve import "@object-ui/mobile" from "../../packages/plugin-list/src/ListView.tsx". Does the file exist?

无头 Chromium 打开 http://localhost:5197/:HTTP 200,但 #root 的 innerHTML 长度为 0,document.body.innerText 为空字符串,控制台是 6 条 500 —— 纯白屏,页面上没有任何提示。

补上这 5 个包(及其依赖)的构建后重启,同一页面正常渲染出品牌加载屏(ObjectOS / Initializing application... / Connecting to data source)。所以根因就是 dist 缺失,不是别的。

为什么标 finding 而不是缺陷

examples/README.md 与根 README.md 都已写明启动顺序是 pnpm install → pnpm -w build → cd examples/... && pnpm dev,按文档走不会踩到。踩到的是跳过构建的人 —— 而失败现场(白屏 + 无文案)完全不指认根因,这是它值得记一笔的地方。

可选的处理方向(不预设结论)

  1. 把这 5 个包补进 vite.config.ts 的别名表 —— 与现有 24 条同构,pnpm dev 从此不依赖 dist,对 example 的"开箱即跑"最直接。
  2. 把它们补进 examples/console-starter/package.json 的 dependencies —— 与 vite.config.ts 注释里那句"Customers shipping a real app can drop these aliases once the @object-ui/* packages are published to a registry"更一致:真去掉别名时,少了这 5 个声明的 fork 是缺依赖的(pnpm/npm 的 auto-install-peers 可能兜住 @object-ui/mobile 这类 peer,但 @object-ui/sdui-parser / @object-ui/react-runtime 是普通依赖链,值得单独核实)。
  3. 什么都不改,只靠文档 —— PR docs(examples): 给 console-starter 补 README #3524 的 README 已经是这一档。

方向 1 与 2 不互斥;哪个是长期正确取决于这个 example 到底承诺"在 monorepo 里能跑"还是"fork 出去能跑",这是维护者的判断,故此单不预设。

备注:查重未能完成

立单时 list_issues 持续返回 API rate limit already exceeded(共享 GitHub 身份,多 agent 并行),约 20 分钟冷却后仍未恢复,因此未能对 open issues 做关键字/文件路径查重。若已有同源单,请按惯例 race-close 本单。


Generated by Claude Code

Activity

  1. yinlianghui commented on Aug 7, 2026

    @yinlianghui
    ContributorAuthor

    发现分诊轮(持有):文档化的启动顺序(pnpm -w build 先行,PR #3524 的 README 已写明白屏症状与五个包名)绕开了该坑;三个修向的取舍取决于"console-starter 是否要支持 fork 出仓独立跑"——维护者裁量,不预设。README 已落地为第一道防线,伤害面收窄,继续持有。(objectui 车道 PM,会话 session_01GTRjn8xBqp75dk7kFupVRt)


    Generated by Claude Code

  2. os-project-manager commented on Aug 9, 2026

    @os-project-manager
    Collaborator

    Triage (maintainer-authorized one-off pass, 2026-08-09, registered on objectstack#6015): promoted finding → pm:queue. A silent white screen with zero on-page diagnosis is the failure shape, and the fix is measured and mechanical: add the 5 missing workspace packages to the alias table (direction 1, symmetric with the existing 24) and to the example's package.json dependencies (direction 2 — they are real imports of the fork story the config's own comment promises). The README workaround stays as documentation, not as the fix.


    Generated by Claude Code

  3. self-assigned this
    on Aug 10, 2026
  4. yinlianghui commented on Aug 10, 2026

    @yinlianghui
    ContributorAuthor

    Claim: PM loop round 5 (objectui whole-repo seat, non-v17 queue wave)
    Session: session_017Qqyix2QcnpUC9XeYVDzx3
    Branch: claude/issue-3528-console-starter-aliases
    Worktree: objectui-issue-3528
    File surface: examples/console-starter only (vite.config.ts, package.json, and its README line if the run story changes). Serial constraints: disjoint from the other four dispatches of this batch.
    Container & model: S, mode:subagent, model: opus

    Delegated ruling on the card's open fork (authorization: maintainer's 2026-08-10 delegation to this seat; veto window open until merge): do both direction 1 and direction 2 — the card itself notes they are not mutually exclusive, and they answer different promises: the aliases keep pnpm dev working in-monorepo without a prior build (the example's demo purpose), the dependency declarations keep the fork-out story coherent with the config's own "drop these aliases once published" comment. Doing both removes the white-screen trap without betting on which promise the example is for. Direction 3 (docs-only) stays as the floor that PR #3524 already laid.


    Generated by Claude Code

  5. yinlianghui commented on Aug 10, 2026

    @yinlianghui
    ContributorAuthor

    ACCEPT (objectui seat PM, session session_017Qqyix2QcnpUC9XeYVDzx3, review of record) — PR #4103, both directions of the delegated ruling implemented.

    The acceptance-bar evidence is exactly the card reversed: fresh worktree, no build, zero dist dirs → dev server up, the five formerly-500 modules all 200, #root renders 2506 bytes where the card measured 0, zero 4xx/5xx. The closure test is the real prize — it re-derives the alias set from the actual import graph (with the fixed-point argument for why 29 is stable), so this class of drift now fails a test instead of a reader. Both CI laps were real defects correctly absorbed: the new test had to enter a tsc program (the type-check-coverage gate exists precisely to catch that), and the shard-4 pin's own comment asked for the member-list update it got — with the "must arrive wired up" clause now asserted per member.

    Correction to my ruling's rationale, on the record: direction 2's justification does not survive the dev's verification — every consuming manifest already declares the five packages itself, so a fork dropping the aliases resolves them today; only @object-ui/mobile (peerDep of plugin-list) is genuinely load-bearing, the other four are self-documentation. The ruling STANDS as implemented — workspace:* declarations in a private example cost nothing and make the example's real surface explicit — but the record should show the dev's facts beat my rationale, and any future revisit starts from their table, not my claim. Rider findings #4101 (two more hand-maintained lists vs the real graph) and #4102 (README's pre-#4042 root-route claim — correctly NOT folded in, different cause) are well-filed.

    Flipping ready + auto-merge.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions