Skip to content

perf(console): 注册后 3-6s 白屏无 loading;每次硬导航都过全屏「正在初始化应用程序」 #2628

Closed

Description

@os-zhuang

现象(staging E2E 2026-07-17)

  1. 注册成功 → /_console/home 之间 3–6 秒纯白屏(无任何 loading 指示),期间 console 有若干「HTTP request failed」噪音(随后自愈)。
  2. CP 与 env 的 console SPA 每次硬导航(整页加载)都要过全屏「正在初始化应用程序…正在连接数据源/加载配置/准备工作区」,常见 3–15 秒。SPA 内路由不受影响,但新用户流程里硬导航不少(注册跳转、打开环境、外链进入)。

影响

新用户旅程的每个关键节点都吃一次「初始化税」。P2。

修复方向(分层)

  • 便宜:白屏窗口给全局 spinner/骨架;init 屏出现前的空档也补 loading
  • 中等:init 各步骤并行化/缓存(auth config、discovery、meta 首包),二次访问走缓存跳过全屏 init
  • 结构:评估 init 屏是否必须阻塞首屏(渐进渲染 home 骨架)

🤖 Generated with Claude Code

Activity

  1. self-assigned this
    on Jul 22, 2026
  2. os-zhuang commented on Aug 6, 2026

    @os-zhuang
    ContributorAuthor

    分诊:pm:queue(⚠️ 限定范围:第一档「白屏期无任何指示」)

    ⛔ objectui 仓内单不打 domain:*(#5468)。

    落点锚定(读代码,不按标题猜)

    origin/main(d003a88)上,「正在初始化应用程序 / 正在连接数据源 / 加载配置 / 准备工作区」这组文案的渲染方是 packages/app-shell/src/chrome/LoadingScreen.tsx(文案键在 packages/i18n/src/locales/*.ts 十语言齐备)。⇒ 本单不是 cloud 侧问题,落点在 objectui 仓内,本仓可闭环。

    现象 1(注册成功 → /_console/home 之间 3–6 秒纯白屏)与现象 2(硬导航过全屏 init)是两个不同的空档:白屏发生在 LoadingScreen 出现之前(bundle/首屏挂载前),init 屏是它出现之后。修法因此不同,正文的分层已经说对了。

    入队范围(dev 请只做第一档)

    • 白屏窗口给出可见指示:在 LoadingScreen 挂载之前的空档补一个最小骨架/spinner(HTML 层或极早期挂载,不能依赖 React 首屏完成)。验收:注册跳转与硬导航全程无纯白帧。

    ⛔ 明确排除

    • 第二档(init 各步并行化 / 二次访问走缓存跳过全屏 init) —— 需要先测出 auth config / discovery / meta 首包各自的耗时占比,否则是盲优化;且缓存跳过 init 会改变「什么时候算准备好」的语义,属产品判断。
    • 第三档(评估 init 是否必须阻塞首屏、渐进渲染 home 骨架) —— 结构改造,与 console-ia 一族相关,应独立立卡。

    过时前提

    正文实测日期 2026-07-17(staging E2E),距今 20 天。未复验实际耗时(需真实 staging 环境,本座位不做浏览器验证)。⇒ 派发前请 dev 先本地/staging 复现一次并记录当前秒数:若白屏已被其它改动压到亚秒级,本单应改判为关闭而不是修 —— 这一条写进派发令,不要让 dev 直接开始改。


    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  3. added
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    on Aug 21, 2026
  4. removed their assignment
    on Aug 23, 2026
  5. os-zhuang commented on Aug 23, 2026

    @os-zhuang
    ContributorAuthor

    清 assignee — objectstack#11196 维护者裁决 2026-08-23「A:本席清 agent 残留」,skills 席 session 757f0dc0-5dae-51d7-9053-c15c57ebfe3b。证据:assignee 自 07-17 立卡起即在(共享 agent 身份),无认领评论、无在飞分支;08-06 分诊限定范围入 pm:queue——不构成协议意义上的认领,是残留(#11196 根因 4)。标签未动;认领席按协议 assign + 声明即可。


    Generated by Claude Code

  6. os-support-ai commented on Aug 25, 2026

    @os-support-ai
    Collaborator

    Claim — domain:ui @ objectui execution seat

    PM session session_011SfZeFWrhGLHmfq61xbz4q (os-support-ai). Branch claude/issue-2628-console-white-frame. Labels pm:queue → pm:dispatched in the same stroke as the assign.

    Assigning per the 2026-08-23 note on this card: the previous assignee was agent residue, not a claim (shared identity, no claim comment, no branch), cleared under the objectstack#11196 ruling, with "认领席按协议 assign + 声明即可". This comment is that declaration.

    Pre-dispatch gate — all three steps

    Thread read: two comments, ⛔ no maintainer ruling, no Blocked-by:, no live claim. The 2026-08-06 triage comment carries two binding constraints, both reproduced in the dispatch order. Shadow check: no sibling card covers the white-frame window. Premise: ⚠️ deliberately not re-derived by me — see below; that is the dev's first task, not mine.

    ⛔ The scope triage fixed, reproduced verbatim into the dispatch

    In scope — tier 1 only: give the white-frame window a visible indication. The gap is before LoadingScreen mounts (bundle/first-paint), so the fix cannot depend on React having finished — an HTML-layer skeleton or a very early mount. Acceptance: no pure-white frame across either the post-registration redirect or a hard navigation.

    ⛔ Explicitly excluded by triage:

    • Tier 2 (parallelising the init steps / skipping the full-screen init on a cached second visit) — blind optimisation without first measuring the auth-config / discovery / meta first-packet shares, and cache-skipping changes the semantics of "when is it ready", which is a product judgement.
    • Tier 3 (whether init must block first paint at all; progressive home skeleton) — structural, related to the console-ia family, needs its own card.

    ⭐ Note the mechanism triage established by reading code rather than guessing from the title: the white frame and the init screen are two different gaps — the white frame happens before LoadingScreen.tsx appears, the init screen after. Different windows, different fixes. Only the first is this card.

    ⚠️ The binding stale-premise clause — triage asked for this in the dispatch, and it is there

    The card's timings (3–6 s white frame) were measured 2026-07-17 on staging. Triage flagged that as 20 days stale and said so explicitly: "派发前请 dev 先本地/staging 复现一次并记录当前秒数:若白屏已被其它改动压到亚秒级,本单应改判为关闭而不是修 —— 这一条写进派发令,不要让 dev 直接开始改。"

    It is now ~40 days stale. So the dispatch orders: measure the current white-frame duration first, before any code. If it is already sub-second, ⛔ do not fix — report premise-false and recommend closing. ⭐ A no-code return with a measurement is the correct delivery on this card, and it is the outcome I would rather have than a fix for a window that no longer exists.

    Triage could not do that measurement itself ("本座位不做浏览器验证"). A dev can: Chromium and Playwright are available in the dev environment.

    packages/app-shell/src/chrome/ and the console entry path — disjoint from the three live claims: #5853 (packages/types + plugin-grid + renderers/complex/), #6361 (two manifests), #5902 (plugin-kanban / plugin-calendar / occSave.tsx).


    Generated by Claude Code

  7. claude commented on Aug 25, 2026

    @claude
    Contributor

    os-dev-report

    {
    "issue": 2628,
    "status": "done",
    "branch": "claude/issue-2628-console-white-frame",
    "head_sha": "57d3de441cf03f8f69a543f38164fb3992c01f7a",
    "pr": "#6380",
    "pr_number": 6380,
    "premise_still_valid": true,
    "summary": "MEASURED FIRST, as ordered: the premise HOLDS, so this is a fix and not a close. On a real production build of apps/console the pure-white window before LoadingScreen mounts is 1516-1655 ms on an unthrottled localhost, 2307-2407 ms at 20 Mbps/80 ms RTT, and 5661-5716 ms on a Fast 4G profile — 2.21 MB across 64 requests before one pixel of content, and the Fast-4G column reproduces the card's reported 3-6 s. Tier 1 only: the indicator (markup, inline styles, one classic inline script) now ships in apps/console/index.html, so it paints from the HTML parser before the first chunk is requested, and is removed on React's first commit into #root. Post-fix the same window is 194-230 / 284-342 / 570-588 ms, and 120-144 / 548-556 ms with the screencast overhead removed. Tier 2 and tier 3 untouched.",
    "measurements": {
    "method": "apps/console production build served locally with the two pre-render boot endpoints mocked; Playwright + Chromium, cache disabled, fresh context per run. TWO independent readings that agreed within 2-7 ms every run: (A) CDP Page.startScreencast, every swapped frame decoded and classified pixel-by-pixel, white = no channel below 242; (B) Paint Timing first-contentful-paint. Network shaped with CDP Network.emulateNetworkConditions.",
    "white_frame_ms_before": {
    "localhost": "1516-1655",
    "broadband_20Mbps_80ms": "2307-2407",
    "fast4g_4Mbps_70ms": "5661-5716"
    },
    "white_frame_ms_after": {
    "localhost": "194-230",
    "broadband_20Mbps_80ms": "284-342",
    "fast4g_4Mbps_70ms": "570-588"
    },
    "white_frame_ms_after_without_screencast_overhead": {
    "localhost": "120-144",
    "fast4g_4Mbps_70ms": "548-556"
    },
    "before_after_are_real_builds_of_both_trees": "index.html checked back to f53a8d0, rebuilt for real (mutation confirmed on disk AND in dist/index.html), measured, then restored and rebuilt; restore proven byte-identical (git hash-object == git rev-parse HEAD:apps/console/index.html).",
    "loadingscreen_not_delayed": "A/B on the IDENTICAL artifact, only variable an injected #boot-splash{display:none}: React first commit 1166-1363 ms painting vs 1149-1506 ms suppressed (localhost), 5577-5648 vs 5606-5656 (Fast 4G) — indistinguishable, while first paint moves from 5632-5688 to 548-556 ms.",
    "caveat": "This is a LOCAL production-build boot with mocked API endpoints, not staging. It establishes the structural fact and a floor; it does not reproduce staging's exact latency. The inference used is one-directional and safe: the local floor already exceeds a second with zero network, so the window is material a fortiori on any real link."
    },
    "tests": "Gate union re-run AFTER the final commit, at 57d3de4, working tree clean, exit codes captured before any pipe. vitest apps/console/src/tests/{bootSplash,insecure-origin-crypto,insecure-origin-crypto.placement,runtimeConfigBootDedup,localizationBootDedup} EXIT=0 "Test Files 5 passed (5) / Tests 48 passed (48)"; pnpm --filter @object-ui/console run lint EXIT=0; pnpm run lint:root EXIT=0; pnpm --filter @object-ui/console run type-check EXIT=0; pnpm run type-check:e2e EXIT=0; pnpm run check:control-bytes EXIT=0 "OK (scanned 5249 tracked text file(s); skipped 85 binary)"; pnpm run check:vi-mock-specifiers EXIT=0 "OK (3760 tracked source file(s), 2072 test-named…)"; pnpm run check:shell-escape-residue EXIT=0 "OK (4/4 root(s) resolved…)"; check-changeset-presence EXIT=0 "2 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)"; check-changeset-fixed EXIT=0; check-changeset-no-major EXIT=0 "No changeset declares a major bump"; check-eager-closure-budget EXIT=0 "aggregate closure 3223.1 KB measured / 3266.6 KB ceiling"; playwright --project=chromium e2e/console-boot-indicator.spec.ts + e2e/console-rendering.spec.ts EXIT=0 "7 passed". Every pnpm --filter run echoed its script name, so none is the silent zero-match. RED BEFORE / GREEN AFTER on both committed instruments: cutting the 609-byte splash element out of apps/console/index.html (mutation confirmed by sha256 before/after and by counting occurrences outside comments) fails 2 of 15 unit tests, and cutting it from the served dist/index.html (server confirmed returning 0 occurrences) fails all 3 e2e tests, the timing one with "first-contentful-paint (1344ms) must precede React's first commit (1276ms)"; both restored and proven byte-identical, both green again.",
    "instrument_limits": "Neither COMMITTED instrument reads pixels. The unit test grades the shipped document plus the script executed against a real DOM, and sees no timing at all. The e2e spec sees ORDER (first-contentful-paint vs React first commit) and CAUSE (with page.route aborting every .js, the indicator still renders) against the production build, but not whether a frame was literally white. The pixel-level reading is the screencast run above, which is NOT in CI: it needs a throttled profile per run and is chromium-only. All three are stated as such in the files and in the PR body.",
    "gates": {
    "union_at": "57d3de441",
    "all_exit_0": true,
    "red_before_green_after": true,
    "ci_convergence": "in_progress — reported at draft-PR time per the standing contract; PM reads the real gate job conclusions."
    },
    "open_questions": [],
    "out_of_scope_findings": [
    "filed as #6378: a one-frame white flash AFTER LoadingScreen first paints (40-230 ms), 4 of 9 pre-fix and 3 of 9 post-fix full-boot runs — a different window from this card, and n=9 a side does not separate those two numbers.",
    "filed as #6379: three render-blocking stylesheets (largest 362 KB raw / 47 KB gzipped) floor first paint at ~550 ms on Fast 4G no matter what the HTML shell does; every route out of it is structural (FOUC semantics for the whole app)."
    ]
    }


    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

Labels

domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpm:dispatched

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions