Uh oh!
There was an error while loading. Please reload this page.
fix(runner): 站内导航保留 query string,?api= 不再被抹掉 - #3594
Merged
Merged
Conversation
`handleNavigate` 原先 `pushState({}, '', to)` 推的是侧栏给的裸路径,
地址栏上的 query 在第一次点击后就没了。memo 住的 loader 让当前会话
看起来正常,但 F5 或把 URL 分享出去时 `params.get('api')` 读到 null,
静默退回(正常安装里为空的)LocalBundleLoader,页面变成 Page not found,
而现场没有任何东西指认「API 基址丢了」。
按 ADR-0054 C3「可寻址状态放 URL」,导航时把当前 query string 一并带走。
保留的是**整个** query,不是只挑 `api`:runner 自己只读 `api`
(`App.tsx`),但它渲染的树里 `@object-ui/core` 的 `parseDebugFlags` /
`@object-ui/react` 的 `useDebugMode` 同样直接读 `window.location.search`
(`?__debug`、`?__debug_schema` 等),只搬 `api` 会把第二类参数留在原地
继续丢 —— 同一种静默丢失,只是爆炸半径小一点。
目标路径若自带 query 则原样保留、同名参数以它为准,其余当前参数并在其后,
绝不拼出 `path?a=1?b=2` 这种畸形 URL。读取侧无需改动:`currentPath` 初值
与 popstate 都只读 `location.pathname`,不受 query 影响。
Fixes#3578The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
yinlianghui
marked this pull request as ready for review
August 7, 2026 15:17
Uh oh!
There was an error while loading. Please reload this page.
This was referenced Aug 7, 2026
Closed
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#3578
问题
packages/runner/src/App.tsx的handleNavigate原先是window.history.pushState({}, '', to)——to是侧栏导航项给的裸路径,于是地址栏上的 query string 在第一次点击后就没了。loader 被
useMemo(..., [])memo 住,所以当前会话看起来一切正常;真正的代价在会话之外:params.get('api')读到 null → 退回LocalBundleLoader,而src/app-data/在正常安装里是空的(gitignore),于是页面变成Page not found。而且失败现场不指认根因:没有任何提示说「API 基址丢了」,控制台只打印
📦 Using Local Bundle Loader。裁定与做法
按 ADR-0054 C3「可寻址状态放 URL」——「当前指向哪个后端」是典型的可寻址状态(会被分享、刷新后期待还在)——采用方向 1:导航时把当前 query string 一并带走。
保留整个 query,还是只保留
api?先量了再定apipackages/runner/src/App.tsx:45-46(git grep在packages/runner/src下的唯一一处 query 读取)__debug/__debug_schema/__debug_perf/__debug_data/__debug_expr/__debug_events/__debug_registrypackages/core/src/utils/debug.ts:39-50(parseDebugFlags)、packages/core/src/utils/debug.ts:86(isDebugEnabled)、packages/react/src/hooks/useDebugMode.ts:51所以
api不是今天唯一有语义的参数 —— runner 依赖@object-ui/react/@object-ui/core,那套 debug 开关同样直接读window.location.search,同样被裸路径 pushState 抹掉。只搬api会把第二类参数留在原地继续丢,是同一种静默丢失,只是爆炸半径小一点。故保留整个 query string —— 也最少惊讶,并且以后谁再开始读 query 都自动受益。改在哪
只改
handleNavigate一处。读取侧经测量无需改动:currentPath的初值(App.tsx:39)和 popstate handler(App.tsx:80)都只读location.pathname,不受 query 影响;loader 的useMemo依旧是挂载时读一次 —— 本 PR 修的正是「刷新时它还能读到」。新增的
withPreservedQuery(to, currentSearch):to是裸路径):把当前 query string 原样接上,不做重编码,地址栏保持用户输入的样子。to,不会多出一个空的?。to自带 query:它自己的参数保留且同名优先,其余当前参数并在其后 —— 绝不拼出path?a=1?b=2这种畸形 URL(这条分支会经URLSearchParams重建,值按标准做百分号编码,是同一批参数的规范拼法)。测试
新增
packages/runner/src/App.navigation.test.tsx,4 条,驱动真实组件(stub 掉 loader,因为src/app-data/是 gitignore 的),所以对未修改的源码也有意义。反向验证(先预测方向,再跑):预测 3 红 1 绿 —— 三条「保留」断言在旧代码下必红,而「无 query 时不多加
?」那条在旧代码下必绿(裸路径天然满足它),它防的是新逻辑过度施加,不是回归探测器。在未修改的App.tsx上实跑,与预测完全一致:改完后全绿:
文档同步
PR #3581 本小时刚把这个行为如实写成注意事项;修复落地后那段话就变成在描述一个已修复的缺陷,故一并改掉:
content/docs/utilities/runner.mdx—— 「Read once, at mount」那条 caveat 重写为新行为(query 跟着走、刷新/分享可用;整串 query 而不只是api;目标自带 query 时的合并规则)。「挂载时读一次」这半句仍然属实(不刷新地改地址栏不生效),予以保留。packages/runner/README.md:91-92—— 同一句缺陷描述在包 README 里还有一份(「the caveat that in-app navigation drops?api=from the address bar」),同步改掉。这一处超出了派单的文件面(派单只点了 mdx),但它和 mdx 那句是同一个事实的两份拷贝,留着就是在同一个 PR 里发布一句已知为假的话。请 review 时确认;要退回随时可以只 revert 这两行。越界说明
packages/runner/tsconfig.test.json加了一行"types": ["vite/client"]。原因不是顺手清理:新测试是 runner 第一个importApp.tsx的测试,把src/lib/MetadataLoader.ts拉进了tsconfig.test.json的 program,而该文件用了import.meta.glob;tsconfig.test.jsonextends 的是根 tsconfig(不是 Vite 应用,不带vite/client),于是tsc -p tsconfig.test.json报 3 条TS2339: Property 'glob' does not exist on type 'ImportMeta'。这是本 PR 引入的,不是既有问题(把新测试文件挪走后type-check立刻 exit 0,已实测)—— 修法与packages/{layout,plugin-calendar,plugin-report,types}/tsconfig.test.json既有的types声明同一形状。Changeset
.changeset/runner-preserve-query-on-navigate.md——@object-ui/runner: patch(用户可见行为修复)。Generated by Claude Code