fix(web): 次级页稳定外壳与缓存预取,跨部署导航自愈(BUG-966/967)
This commit is contained in:
+43
-7
@@ -12533,7 +12533,7 @@
|
||||
|
||||
## BUG-965 | 侧栏「星盘 / 星历 / 我的报告」点了不跳转,账户入口也没反应
|
||||
|
||||
- 状态:investigating(触发条件已由产品复现确认,修复未做)
|
||||
- 状态:resolved(由 BUG-967 修复)
|
||||
- 首次发现:2026-09-18
|
||||
- 最近更新:2026-09-18
|
||||
- 影响面:`AppSidebar` 的 `NAV_PAGES` 链接与页脚账户入口;staging `877128ce`
|
||||
@@ -12545,12 +12545,48 @@
|
||||
3. 链接是真链接:三项导航是 `SidebarMenuLink` → `next/link` 的 `<Link href>`,`onClick={leaveChat}` 只做 `persistLoginSessionReturn()` 与关抽屉,**没有 `preventDefault`**。
|
||||
4. 没有覆盖桌面侧栏的 `pointer-events: none` 或 `inert`:`inert` 只出现在移动端抽屉、时间轴折叠体、`SidebarInset`(`insetInert = modalOpen`,只盖正文区不盖侧栏)。
|
||||
5. 次级页页脚是 `Link href="/"`(账户菜单只在 `/`),因此「在次级页点头像」应当跳回首页而不是没反应。
|
||||
- 待取证据:控制台报错原文与 Network 面板是否有 404 的 `/_next/static/**`;点击时所在页面的 URL;该标签页是否在 17:12 部署之前就已打开;硬刷新(Cmd+Shift+R)后是否恢复。
|
||||
- 根因(按复现结论):标签页跨过部署后,客户端导航要拉的构建产物已被新镜像替换(构建 id 变了,旧 chunk / RSC 负载不再存在),路由切换静默失败;已经加载好的对话页因为代码都在内存里,照常工作。Next 16 自带的构建不匹配回退在这次没有把用户带到整页重载,具体是被哪一层吞掉(404 形状、Caddy、还是 RSC 负载不匹配的判定)需要在修复单里查证。
|
||||
- 修复方向:见 `docs/tasks/TASK-secondary-page-entry-20260918.md` BUG-967——客户端用编译期注入的 `NEXT_PUBLIC_GIT_COMMIT` 与 `/api/health` 的 `deployment.gitCommit` 比对,发现自己是旧版本就在下一次导航时整页重载,而不是静默失败。
|
||||
- 关联记录:BUG-744~746(侧栏统一为 `Link` 跳转)、BUG-926~929(会话列表单一数据源与外壳搬家)、BUG-936(首屏 bundle 未执行)
|
||||
- 复发自:待确认
|
||||
- 修复版本:待发布
|
||||
- 根因:见 BUG-967。标签页跨过部署后,客户端导航要拉的构建产物已被新镜像替换;Next 16.3.1 自带的构建不匹配回退在自托管 + 预取缓存这条路上没有把用户带到整页重载,点击表现为静默无反应。已经加载好的对话页因为代码都在内存里,照常工作。
|
||||
- 修复:BUG-967 的版本比对自愈。旧标签页在下一次站内跳转走 `window.location.assign`。
|
||||
- 验证:见 BUG-967。
|
||||
- 防复发:见 BUG-967。不得再把「刷新就好」当成侧栏无响应的结案。
|
||||
- 关联记录:BUG-967、BUG-204、BUG-744~746、BUG-926~929、BUG-936
|
||||
- 复发自:BUG-204 同类(跨发布客户端导航),那次修的是 `deploymentId` / `?dpl=`,在 Vercel 上靠部署路由 404 触发 MPA;本仓是自托管单镜像,那条路径不成立。
|
||||
- 修复版本:本轮提交
|
||||
|
||||
## BUG-966 | 星盘 / 星历 / 我的报告进入时矮等待块推挤成高正文
|
||||
|
||||
- 状态:resolved
|
||||
- 首次发现:2026-09-18
|
||||
- 最近更新:2026-09-18
|
||||
- 影响面:`chart-page-view.tsx`、`ephemeris-page.tsx`、`personal-report-center.tsx`、`use-chart-page.ts`、`SecondaryHeader`
|
||||
- 用户现象:从侧栏进「星盘 / 星历 / 我的报告」有一瞬间抖动。
|
||||
- 触发条件:进入这三页,尤其是同一会话里每次进入(没有首屏缓存)。
|
||||
- 根因:三页各写各的等待布局——先渲染 46px 标题加一行短等待文案,数据到达后整块换成高正文。`SecondaryHeader` 的 `note` 未到时不渲染,标题区二次填充。`use-chart-page` 进页才 fetch,零缓存,每次都重放中间态。产品 2026-09-18 选定方案一:消灭中间态,不加 spinner,红线不动。
|
||||
- 修复:三页共用 `SecondaryPageShell`(标题行高度固定、note 槽占位不塌、内容区撑满剩余视口,等待文案居中在该区)。星盘 / 星历 / 报告首屏进模块级缓存,同一会话再进直接用上次结果并后台静默刷新。侧栏三项在 `pointerenter` / `pointerdown` 预热数据。等待句仍是静态句(「这一张盘还没拿到。」等),没有 spinner / 骨架 / 「正在加载」。
|
||||
- 验证:`frontend/tests/secondary-page-entry.test.ts`(三页 import 共享外壳、暖缓存第二次不经 null 等待、预取命中同一 inflight、CSS 内容区 min-height:0 且等待居中);既有 `chart-page-view` / `ephemeris-page` / sidebar 合同。浏览器量高度见 `docs/testing/secondary-page-entry-20260918.md`(无 Chrome)。
|
||||
- 防复发:次级页进入不得再各写一套等待布局。揭幕后不得加 spinner / 骨架 / 「正在加载」。缓存必须模块级,组件 unmount 不能丢掉。
|
||||
- 关联记录:BUG-716、BUG-717、BUG-745
|
||||
- 复发自:无
|
||||
- 修复版本:本轮提交
|
||||
|
||||
## BUG-967 | 跨部署旧标签页的客户端导航静默失效
|
||||
|
||||
- 状态:resolved
|
||||
- 首次发现:2026-09-18
|
||||
- 最近更新:2026-09-18
|
||||
- 影响面:`AppLink`、`app-navigation.ts`、`StaleBuildGuard`、侧栏 `NAV_PAGES` 与次级页账户入口、Web 镜像 `NEXT_PUBLIC_GIT_COMMIT`
|
||||
- 用户现象:见 BUG-965。
|
||||
- 触发条件:标签页在一次部署之前打开,部署后不刷新,点站内次级页或账户入口。
|
||||
- 根因(查证 Next 16.3.1 源码,不得跳过):
|
||||
1. 不匹配回退写在 `fetchServerResponse`:RSC 不是 `text/x-component`、或非 2xx、或 `x-nextjs-deployment-id` / `flightResponse.b` ≠ `getNavigationBuildId()` 时才 `doMpaNavigation`。`<Link>` 进页时已经把 `/chart` `/ephemeris` `/reports` 的 Flight 预取进内存;点击走缓存、不再 fetch,这条检查根本不跑。
|
||||
2. 自托管只有当前镜像。Caddy 对 `/_next/static` 没有改写,只是 `reverse_proxy web:3000`。`?dpl=` 是 Vercel 按部署分流的参数,在本机被忽略。目标路由在新镜像上仍 200 返回新的 Flight,`!res.ok` 也不成立。
|
||||
3. `handleHardNavError` / `useNavFailureHandler` 编译期开关 `__NEXT_APP_NAV_FAIL_HANDLING`,standalone 默认关。旧 chunk 的 `ChunkLoadError` 若被 router reducer 吃掉,既有 `StaleClientRecovery`(只听 `window.error` / `unhandledrejection`)也看不见。客户端导航于是表现为点击无反应;挂起的 `useTransition` 还能让同一页的账户入口一起没反应。
|
||||
- 修复:编译期 `NEXT_PUBLIC_GIT_COMMIT`(Docker 构建时与 `NEXT_DEPLOYMENT_ID` 同值写入)对照 `/api/health` `.deployment.gitCommit`。页面重新可见时拉一次 health,导航前读这份快照。不一致则 `window.location.assign`,一致则继续客户端路由。health 失败不强制刷新。无轮询、无定时重载。
|
||||
- 验证:合同测试——版本不一致走 `assign`,一致走传入的 `router.push` / 不 preventDefault;health 失败或 commit 为 `unknown` 不强制跳。真机跨部署见 `docs/testing/secondary-page-entry-20260918.md`。
|
||||
- 防复发:站内跨布局跳转走 `AppLink` / `navigateAppPath`,不得假定 Next 的 mismatch fallback 在自托管上会救场。不得用「每次导航都整页重载」或定时刷新糊过去。
|
||||
- 关联记录:BUG-965、BUG-204
|
||||
- 复发自:BUG-204
|
||||
- 修复版本:本轮提交
|
||||
|
||||
## BUG-955 | 输入处理器 abort 与「合同未完成」同码,窗口装配失败藏了四周
|
||||
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
# PROGRESS · 次级页进入时的等待态与抖动(2026-09-18)
|
||||
|
||||
分支:`codex/secondary-page-entry-20260918`
|
||||
基线:`origin/staging` @ `1061514f`(任务书写的 `41902067` 是写单时的 head;本 worktree 按开工指令跟当前 `origin/staging`)
|
||||
方案:产品 2026-09-18 选定方案一。方案 B 未做。
|
||||
|
||||
## BUG-967 调查:Next 16.3.1 的 mismatch fallback 为什么没开火
|
||||
|
||||
对照 `next@16.3.1` 源码(GitHub tag `v16.3.1`),不是猜的。
|
||||
|
||||
### Next 自己会在什么时候整页跳
|
||||
|
||||
`packages/next/src/client/components/router-reducer/fetch-server-response.ts`:
|
||||
|
||||
1. RSC 响应 `Content-Type` 不是 `text/x-component`(export 模式下还接受 `text/plain`),或 `!res.ok`,或没有 body → `doMpaNavigation`。
|
||||
2. 解出 Flight 之后:`(res.headers.get(NEXT_NAV_DEPLOYMENT_ID_HEADER) ?? flightResponse.b) !== getNavigationBuildId()` → 同样 MPA。
|
||||
3. `app-router.tsx` 看到 `pushRef.mpaNavigation` 才 `location.assign` / `replace`,并 `throw unresolvedThenable` 卡住当前树。
|
||||
|
||||
另有 `nav-failure-handler.ts` 的 `handleHardNavError`:导航过程中未捕获错误则 `window.location.href = window.next.__pendingUrl`。**整份文件包在 `process.env.__NEXT_APP_NAV_FAIL_HANDLING` 里**,standalone 默认不打开。
|
||||
|
||||
既有 `StaleClientRecovery` 只在 `window.error` / `unhandledrejection` 文本像 chunk 失败、且 `sessionStorage` 还没记过一次时 `reload()`。router reducer 如果把 rejection 吃掉,它看不见。
|
||||
|
||||
### 为什么这次三条都不触发
|
||||
|
||||
1. **预取缓存让检查根本不跑。** 侧栏三项是 `<Link>`。标签页在部署前已经打开对话页时,Next 已经把 `/chart` `/ephemeris` `/reports` 的 Flight 预取进内存。点击走这段缓存,不再 `fetchServerResponse`。构建 id 比对、非 2xx、非 Flight Content-Type,全部不执行。
|
||||
2. **自托管没有 Vercel 那种 `?dpl=` 分流。** `next.config.ts` 写了 `deploymentId: process.env.NEXT_DEPLOYMENT_ID`,静态资源带 `?dpl=`。在 Vercel 上这个 query 把请求打到对应部署,旧部署不在了就是 404,于是走条件 1。本仓 Caddy(`deploy/Caddyfile.staging` / `Caddyfile.production.selfhosted`)对 `/_next/static` **没有任何特殊 404 改写**,只 `reverse_proxy web:3000`。主机上只有当前镜像。旧 tab 就算真的去 fetch `/chart`,新服务器仍对这条路径返回 **200 + 新的 Flight**。条件 1 的 `!res.ok` 不成立。BUG-204 当年靠 `deploymentId` 修好的是 Vercel 形状,不是这台 VPS。
|
||||
3. **错误回退开关是关的。** 旧 chunk 404 变成 `ChunkLoadError` 时,默认 standalone 不会把它升级成 MPA。点击看起来像没反应。`app-router.tsx` 若已经丢出 `unresolvedThenable` 或 `startTransition` 一直 pending,同一页上的账户按钮(本就不是 Link)也会一起没反应——这与「对话还能发」不矛盾:对话代码在内存里,路由切换被卡住。
|
||||
|
||||
Caddy 不是元凶:它没有把 404 变成 200 HTML。问题是 **200 的新 Flight** 加上 **根本不再 fetch 的预取缓存**。
|
||||
|
||||
### 自愈怎么做(才没有废掉正常客户端导航)
|
||||
|
||||
- 客户端 commit:构建期 `NEXT_PUBLIC_GIT_COMMIT`(Dockerfile 里与 `NEXT_DEPLOYMENT_ID` 同值写入,不改 workflow)。
|
||||
- 服务端 commit:已有的 `GET /api/health` → `.deployment.gitCommit`(运行时 `GITHUB_SHA`)。
|
||||
- `StaleBuildGuard` 在挂载和 `visibilitychange → visible` 时拉一次 health。不轮询、不定时 reload。
|
||||
- 导航前读这份快照。不一致:`window.location.assign`。一致:原样走 `Link` / `router.push`。health 失败或任一侧是空/`unknown`:不强制跳。
|
||||
|
||||
## BUG-966
|
||||
|
||||
三页改为 `SecondaryPageShell`。`.secondary-page` 是 chat-panel 第二行(`minmax(0,1fr)`),等待与正文同一格子;等待句居中。`SecondaryHeader reserveNote` 让出生行晚到时标题行不塌。模块级缓存 + 侧栏 `pointerenter`/`pointerdown` 预取。报告列表首屏去掉 `InlineSpinner`「正在读取报告…」,改静态句「报告列表还没拿到。」刷新按钮上的 spinner 仍是用户点的动作,DESIGN 允许。
|
||||
|
||||
未做方案 B(延迟揭幕)。
|
||||
|
||||
## 测试
|
||||
|
||||
| 命令 | 结果 |
|
||||
| --- | --- |
|
||||
| `npx tsc --noEmit` | 0 错 |
|
||||
| `npm run lint` | 0 error(既有 120 warning,本轮文件未新增) |
|
||||
| 定向:`secondary-page-entry` / `chart-page-view` / `ephemeris-page` / `sidebar-contract` / `stale-client-recovery` / `personal-report-entry` / `chat-navigation-a11y-contract` / `class-name-definition-contract` | 114 / 114 |
|
||||
| `personal-report-view.test.ts` | 通过(详情页仍用 `SecondaryHeader`) |
|
||||
| `next build` | compile + tsc 过;收集 `/api/daily-starlanguage` 时 Windows `EPERM` 无法 symlink skill runtime。环境缺口,与本轮无关。`/` Static 与 gzip 未在本机量到。 |
|
||||
|
||||
无 Chrome:高度真机清单在 `docs/testing/secondary-page-entry-20260918.md`。无登录态:缓存第二次进入与跨部署自愈的浏览器步骤同样写在那里。
|
||||
|
||||
改过的既有断言:
|
||||
|
||||
| 测试 | 原值 | 新值 | 原因 |
|
||||
| --- | --- | --- | --- |
|
||||
| `sidebar-contract` 只读行 / 页脚 | `<Link className="session-main">`、`<Link className="profile-trigger" href="/">` | `AppLink`,class 与 href 不变 | BUG-967 跨部署自愈;只读行仍是链接、页脚仍去 `/` |
|
||||
|
||||
## 偏离
|
||||
|
||||
- 任务书写 `app/(secondary)/layout.tsx`,当前树是 `app/(app)/layout.tsx`(会话列表单源之后)。外壳挂在这里,没有把路由组改回去。
|
||||
- 报告详情 `/reports/[reportId]` 仍用 `SecondaryHeader` 各阶段一份,不进三页进入抖动的范围;loading.tsx 里的 spinner 本轮不动。
|
||||
@@ -142,7 +142,7 @@
|
||||
| `TASK-contract-degraded-pass4-20260918.md` | `PROGRESS-contract-degraded-pass4-20260918.md` | 验收 review:BUG-956 新增的降级交付路径绕过 Pass 4,保证句原样送达(BUG-959);`uncontractedText` 跨 attempt 不清零,同一轮正文说两遍(960);降级后还空跑一轮 compose(961)。基线 `877128ce` | 待验收 | `e07d5190` |
|
||||
| `TASK-window-consult-contract-20260918.md` §5 | `PROGRESS-window-consult-precompute-20260918.md` | BUG-957:申报时段计算改为服务端预跑并走同请求缓存。产品确认 BUG-954 已在 staging 验证,本轮单独做。不得 `toolChoice: "required"`,本命不预跑 | 待验收 | `efd40d43` |
|
||||
| `TASK-chat-markdown-list-20260918.md` | `PROGRESS-chat-markdown-list-20260918.md` | 真机排版反馈:聊天正文列表**没有项目符号**(Tailwind v4 preflight 清了 `list-style`,`.markdown-list` 没恢复,BUG-962);`promoteDefinitionLists` 把四标题口语体的散文误判成并列项,三段正文被改写成列表(BUG-963,判据太松,收紧而非删除——BUG-356 的场景要留);思考条与正文之间实测 56px=报告 grid gap 24 + 首标题 margin-top 32,后者是被特指度压掉的「首元素清零」规则(BUG-964)。基线 `ea0280c1` | 待验收 | `8b102d52` |
|
||||
| `TASK-secondary-page-entry-20260918.md` | — | 真机反馈:星盘 / 星历 / 报告进入时抖一下——三页都是「矮的等待文案块 → 高的正文块」一次推挤,且 `use-chart-page` 无缓存所以每次进入都抖(BUG-966)。产品已拍板方案一:统一外壳 + 缓存 + 预取消灭中间态,**不加 spinner**,红线不动。另含 BUG-967:标签页跨过部署后客户端导航静默失效(BUG-965 已复现确认,刷新即恢复),要按 `NEXT_PUBLIC_GIT_COMMIT` 与 `/api/health` 比对自愈。基线 `41902067` | 待领取 | — |
|
||||
| `TASK-secondary-page-entry-20260918.md` | `PROGRESS-secondary-page-entry-20260918.md` | 真机反馈:星盘 / 星历 / 报告进入时抖一下——三页都是「矮的等待文案块 → 高的正文块」一次推挤,且 `use-chart-page` 无缓存所以每次进入都抖(BUG-966)。产品已拍板方案一:统一外壳 + 缓存 + 预取消灭中间态,**不加 spinner**,红线不动。另含 BUG-967:标签页跨过部署后客户端导航静默失效(BUG-965 已复现确认,刷新即恢复),要按 `NEXT_PUBLIC_GIT_COMMIT` 与 `/api/health` 比对自愈。基线 `41902067` | 待验收 | `4c69a3dc` |
|
||||
| `TASK-account-dialog-inert-20260918.md` | — | 真机:账户弹窗打开后整个弹窗点不动、退出登录做不了,刷新依旧——`e4e73f56` 把 `SidebarInset` 搬进 layout 后 `inert={modalOpen}` 罩住了没有 portal 的 `AccountDialogOverlay`(BUG-968,P0,代码级确认)。另含 BUG-969:校正「换一件事问」后无下文,服务端已出下一题且快照重算完整,客户端停在开场状态,GET 路由与客户端两端静默,本单只做可观测 + 不静默 + 题干进正文。基线 `1061514f` | 待领取 | — |
|
||||
| `TASK-first-paint-dead-screen-fallback-20260917.md` | — | 真机:首页永远停在「正在载入账户」,兜底全在没跑起来的 bundle 里(BUG-936 investigating)。根 layout 加与 bundle 无关的内联兜底 + 去掉本仓正则后行断言 | 待领取 | — |
|
||||
| `TASK-consultation-answer-start-anchor-20260917.md` | `PROGRESS-consultation-answer-start-anchor-20260917.md` | 主会话回答落在结尾:`useConversationScrollAnchor` 是贴底跟随,流式期间视口钉在最后一个字,回答开头滚出视口;改为发送后问题钉顶、回答向下长、长出视口显示「跳到最新」、末尾动态留白;产品追加拍板:校正面同一语义(推翻 BUG-041/048 贴底),本轮开头 = 用户行或新助手行。BUG 段 930 起 | 已验收(经修复单) | `worktree/green-harbor-5be3` |
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
# 真机清单 · 次级页进入不再推挤 + 跨部署导航自愈(2026-09-18)
|
||||
|
||||
对应 `TASK-secondary-page-entry-20260918.md`、`PROGRESS-secondary-page-entry-20260918.md`、BUG-965 / 966 / 967。
|
||||
|
||||
自动化做不到的部分:需要**浏览器 + 已登录账号**。执行环境无 Chrome、无登录态,因此这些是环境缺口,不是「已通过」。
|
||||
|
||||
准备:桌面 Chrome,宽度 ≥ 1024px,已登录。DevTools → Network 勾上 `Preserve log`。
|
||||
|
||||
## A · 进入三页时外壳高度不变(BUG-966)
|
||||
|
||||
1. 停在 `/`。Console 里先贴:
|
||||
|
||||
```js
|
||||
(() => {
|
||||
const measure = () => {
|
||||
const node = document.querySelector(".secondary-page");
|
||||
if (!node) return null;
|
||||
const r = node.getBoundingClientRect();
|
||||
return { h: Math.round(r.height), top: Math.round(r.top) };
|
||||
};
|
||||
const log = [];
|
||||
const obs = new ResizeObserver(() => log.push({ t: performance.now(), ...measure() }));
|
||||
const start = () => {
|
||||
const node = document.querySelector(".secondary-page");
|
||||
if (!node) { requestAnimationFrame(start); return; }
|
||||
obs.observe(node);
|
||||
log.push({ t: performance.now(), ...measure(), event: "first" });
|
||||
};
|
||||
window.__secondaryPageLog = log;
|
||||
window.__secondaryPageStop = () => { obs.disconnect(); console.table(log); };
|
||||
document.addEventListener("click", (event) => {
|
||||
const a = event.target.closest("a[href='/chart'], a[href='/ephemeris'], a[href='/reports']");
|
||||
if (a) requestAnimationFrame(start);
|
||||
}, true);
|
||||
console.log("ready: click 星盘 / 星历 / 我的报告, then __secondaryPageStop()");
|
||||
})();
|
||||
```
|
||||
|
||||
2. 点侧栏「星盘」。内容出现后立刻在 Console 执行 `__secondaryPageStop()`。
|
||||
- **期望**:表格里所有 `h` 相同(等待态与内容态同高),`top` 不变。
|
||||
- **不期望**:高度从一行文案跳到整页正文;出现转圈、骨架、「正在加载」。
|
||||
3. 对「星历」「我的报告」各做一次。三页的等待句可以不同(盘还没拿到 / 星历还没拿到 / 报告列表还没拿到),但都必须写在 `.secondary-page` 里居中,不能是矮块。
|
||||
|
||||
## B · 第二次进入没有等待句(BUG-966 缓存)
|
||||
|
||||
1. 打开过「星盘」并等到盘出现。
|
||||
2. 点「新建对话」回 `/`(不要刷新)。
|
||||
3. Network Clear,再点「星盘」。
|
||||
- **期望**:第一帧就是盘(或失败句),**没有**「这一张盘还没拿到。」。Network 里可以有一条后台 `/api/chart-view`(静默刷新)。
|
||||
4. 「星历」「我的报告」同样:第二次不得再出现各自的等待句。
|
||||
|
||||
## C · 悬停会预取数据(BUG-966 预取)
|
||||
|
||||
1. 刷新 `/`,Network Clear,筛选 `chart-view|ephemeris|reports`。
|
||||
2. 鼠标移到侧栏「星盘」上,**先不要点**。
|
||||
- **期望**:出现 `GET /api/chart-view`。对「星历」「我的报告」分别是 `/api/ephemeris`、`/api/reports`。
|
||||
3. 再点进去。
|
||||
- **期望**:若预取已完成,进页不再先闪等待句。
|
||||
|
||||
## D · 跨部署旧标签页会在下一次跳转整页重载(BUG-965 / 967)
|
||||
|
||||
这一条必须跨一次真实部署,属环境依赖。
|
||||
|
||||
1. 在 staging 打开 `/` 并停留在对话页(不要关标签)。确认对话还能发、还能收。
|
||||
2. 让负责人发一版新的 staging(或等下一轮门禁部署)。记下新 SHA。
|
||||
3. **不要刷新**这个旧标签。切到别的应用再切回来(触发 `visibilitychange`)。
|
||||
4. Network Clear。点侧栏「星盘」。
|
||||
- **期望**:出现 Type = `document` 的 `/chart` 请求(整页重载),页面打开;不是点击无反应。
|
||||
- 地址栏最终是 `/chart`,之后再点「星历」应走客户端导航(没有新的 document 请求),因为这时已经是新构建。
|
||||
5. 另开一个**部署之后**才打开的新标签,点「星盘」。
|
||||
- **期望**:没有 document 请求(版本一致,仍是客户端路由)。
|
||||
6. 若 health 接口人为断掉(DevTools Offline 只挡 `/api/health` 不挡其它):
|
||||
- **期望**:当前标签继续能点、不强制刷新。
|
||||
|
||||
失败时记下:点击时的 URL、Console 全文、Network 里 `/_next/static` 与 `/chart?_rsc` 的状态码。不要把用户资料贴进仓库。
|
||||
Reference in New Issue
Block a user