Skip to content

fix(site): Playground 注册 layout 组件,并删掉两个非依赖的 transpilePackages 死条目 - #3942

Merged
yinlianghui merged 2 commits into
mainfrom
claude/issue-3904-playground-layout-reg
Aug 9, 2026
Merged

fix(site): Playground 注册 layout 组件,并删掉两个非依赖的 transpilePackages 死条目#3942
yinlianghui merged 2 commits into
mainfrom
claude/issue-3904-playground-layout-reg

Conversation

@yinlianghui

@yinlianghuiyinlianghui commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

Fixes#3904

背景

文档站有 4 个 SchemaRenderer 宿主。#3787 给渲染 catalog 示例的三个加了 registerLayoutBlocks,第四个 —— Playground —— 渲染的是用户手输的 schema,不在那次验收面内,于是今天在 Playground 敲一个 page-header 仍然得到红色 OBJUI-001「Unknown component type」面板,而文档站其它地方都能渲染它。占位符也接不住:page-header 属于 placeholders.tsx 里 opt-in 的 PROTOCOL_COMPONENTS,不在 eager 注册的 PALETTE_PLACEHOLDER_BLOCKS 里,而 registerPlaceholders() 只有 apps/console 调。

同时 apps/site/next.config.mjstranspilePackages 列着两个非依赖包:@object-ui/i18n@object-ui/plugin-aggrid

改动(三个文件)

  1. apps/site/app/playground/page.tsx:模块作用域 import @/app/components/registerLayoutBlocks,与另三个宿主同款。用 @/app/... 别名而非相对路径,是跟随该文件既有的 provider import 写法(相对路径在 app/playground/ 下拼出来反而不同)。
  2. apps/site/next.config.mjs:删掉两个死条目,并把「每一项都必须是本 app 已声明的依赖」连同原因写进注释。
  3. 新增 scripts/__tests__/site-playground-layout-registration-3904.test.ts:把两个面都钉住。

两个条目为什么确实是死的(自行核实,不是照抄 issue)

Next 有两处消费 transpilePackages

  • webpack-config.js 里建的 node_modules/(名字)/ 路径正则;
  • handle-externals.js 里按名字把每一项解析成 包名 + /package.json解析起点是 app 目录;解析成功才记下该包目录,之后按目录前缀判定资源要 bundle 而不是 externalize。

pnpm 严格 linker 下这两个包在 apps/site 根本解析不到 —— 实测 MODULE_NOT_FOUND,而真实依赖给的是 ERR_PACKAGE_PATH_NOT_EXPORTED(找到了包,只是 exports 不暴露 package.json),两者可以干净地区分开。解析不到 ⇒ 不记目录 ⇒ 退回 node_modules/名字/ 子串匹配,而 workspace 包的真实路径是 packages/xxx/dist/...(webpack symlinks: true),也命不中。两条路径都没有,条目零作用。packages/plugin-aggrid 更是整个 workspace 里已经不存在了。

反过来说,剩下 19 项是有作用的:它们能解析到,于是走目录前缀匹配,确实阻止了 externalize。所以这不是「整个数组都是装饰」,只有那两项是死的。

⚠️@object-ui/i18n 那一项当初是「有意加的」,所以单独交代为什么删它安全

审阅时值得先看这一节。根 CHANGELOG.md:565 明确说这一项是为修 SSR 预渲染报错而加:

Site SSR build (@object-ui/site): Added @object-ui/i18n to transpilePackages in next.config.mjs to fix "dynamic usage of require is not supported" error when prerendering the tooltip docs page.

所以它不是「一行装饰」,不能凭 issue 的说法一删了之。查证结果:

  • 加它的是 c4489d0fa(2026-03-31)。那个 commit 对 site 改了 next.config.mjs 这一行,没有同时把 @object-ui/i18n 加成 apps/site 的依赖 —— 有意思的是同一个 commit 给 console 补的是真依赖plugin-chatbot),正好是 site 这半边漏掉的那一步;
  • git log -S '"@object-ui/i18n"' -- apps/site/package.json零命中:它从来没有做过 apps/site 的声明依赖;
  • 当时数组本来就非空,shouldIncludeExternalDirs 早已是开着的,所以这一行唯一可能生效的路径就是「按名字解析」,而那条路径在 pnpm 严格 linker 下解析不到。

实证:删掉该项后完整 next build 预渲染 556/556 页全绿,其中 CHANGELOG 点名的那一页照常产出 —— .next/server/app/docs/components/overlay/tooltip.html,133KB 真实内容(Tooltip 正文在内),dynamic usage of require 零命中。也就是说那个报错并不靠这一项压着。

一处相关细节:@object-ui/i18n 其实是 components/react/fields传递依赖,代码确实进了站点产物 —— 但它一直走的是真实路径 packages/i18n/dist/*.js,本来就不靠这个条目;真正让 workspace 外部目录能被编译的是「transpilePackages 数组非空」这个布尔,删两个名字后数组仍有 19 项,不受影响。这一点也写进了测试。

验收 ②:剩余条目逐一核实

19 项全部是 apps/site/package.jsondependencies,且 apps/site/node_modules/@object-ui/ 下都有 symlink:corecomponentsfieldslayoutreacttypesplugin-calendarplugin-chartsplugin-chatbotplugin-dashboardplugin-editorplugin-formplugin-ganttplugin-gridplugin-kanbanplugin-mapplugin-markdownplugin-timelineplugin-view。这条核实已经机械化,不用下次再手数一遍。

验收 ①:验证层级(如实报告)

apps/site 没有任何测试基建 —— 无 test script、无 vitest config,且根 vitest 的 sharedExclude 直接排除 apps/**。容器里也没有装 Playwright 浏览器(~/.cache/ms-playwright 不存在),所以没有做真浏览器手敲那一步。按 issue 允许的下限做,并额外补了一层构建实证:

  1. 静态断言(新测试,11 个 case 全绿):注册链三段接上 —— Playground import 了 registrar;registrar 从 @object-ui/layout import 并在模块作用域调用registerLayout()(该包 sideEffects: false,只 import 不调用可能被摇掉);而 registerLayout() 真的注册 page-header 这一段,已经由 packages/layout/src/__tests__/page-header-authorable-keys.test.tsx 钉在实现旁边,这里不重复(那个文件是它的归属,且 packages/layout: sideEffects: false contradicts the load-time registerLayout() — a side-effect-only import can be tree-shaken away #3899 正在动那个包)。宿主是发现式枚举的,不是硬编码四个 —— 这个 bug 本来就是「谁都没想起来加的那个宿主」,第五个宿主会被同样地抓住。

  2. 构建差分实证pnpm --filter @object-ui/site build 两次(有/无本次 import),拿预渲染 /playground 页面实际引用的 chunk 去查只属于 registerLayout 的标记:

    标记无本改动有本改动
    responsive-grid105kecdsogrnc.js
    navigation-renderer105kecdsogrnc.js
    app-schema-renderer105kecdsogrnc.js
    页面 chunk 数2022

    顺带说明一个容易被误读的现象:光查 page-header 字符串在两个构建里命中一个 chunk —— 那是 placeholders.tsx 里 opt-in 名单的字符串,不是注册。所以差分用的是上面三个只出现在 registerLayout 里的标记;构建也证明 sideEffects: false 没有把它摇掉。

反向验证(方向先判后跑,两边都是预期的红):去掉 Playground 那行 import,新测试点名 apps/site/app/playground/page.tsx 变红、另三个宿主保持绿;把 @object-ui/i18n 放回 transpilePackages,另一组点名它变红。

一个值得维护者知道的点

pnpm type-checkturbo run type-check覆盖不到本 PR 改的任何文件apps/site 的脚本叫 types:check(不是 type-check),scripts/ 也不是 workspace 包。所以除了全仓 78/78 全绿之外,另外单跑了 pnpm --filter @object-ui/site types:checkpnpm type-check:scripts,都是 0 错。这是既有且登记过的状况(scripts/check-type-check-coverage.mjs 绿,把它算作「1 not compiled」),不是本 PR 引入的,所以没有另开 issue。

顺手记录的仓外发现

已另开 #3944finding 标签,未认领):根 vitest.config.mts 的 alias 表有 4 个指向不存在目录的死条目(@object-ui/engine@object-ui/renderer@object-ui/plugin-aggrid@object-ui/ui),是同一类「配置声明了、依赖图里没有」的漂移。实测这 4 个 specifier 的 import 数都是 0,今天没人碰到,所以按观察类记录、不在本 PR 修(vitest.config.mts 是共享热文件)。

不在本单内

「Playground 组件覆盖面到哪为止」按分诊定界可分割:它现在也没有 plugin-detail,所以 record:* 全渲染不出。那是 Playground 调色板的产品决定,不是这次的注册缺口,本 PR 不碰;packages/layout 也没碰(#3899 的面)。

changeset

不需要。@object-ui/site.changeset/config.jsonignore 列表里(changesets 从不给它发版),另一个改动是 scripts/__tests__/,不属于任何已发布包的 src/node scripts/check-changeset-presence.mjs 输出:No source of a released package changed in this range, so no changeset is owed.


🤖 Generated with Claude Code

https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt

… transpilePackages entries
The docs site has four SchemaRenderer hosts. objectui#3787 added
`registerLayoutBlocks` to the three that render catalog examples; the
Playground renders hand-typed schemas and was outside that acceptance
surface, so typing `page-header` there still produced the red OBJUI-001
"Unknown component type" panel for a component the rest of the site
renders fine. The placeholder net does not catch it either: `page-header`
is in the opt-in PROTOCOL_COMPONENTS of `placeholders.tsx`, and
`registerPlaceholders()` is only called by apps/console.
Also removes `@object-ui/i18n` and `@object-ui/plugin-aggrid` from
`apps/site`'s `transpilePackages`. Next resolves each entry as
`<pkg>/package.json` FROM THE APP DIRECTORY to decide what to bundle
rather than externalize, then matches by directory prefix; under pnpm's
strict linker neither package is resolvable from apps/site
(MODULE_NOT_FOUND, versus ERR_PACKAGE_PATH_NOT_EXPORTED for the real
dependencies), so both entries did nothing while reading as if the site
already supported those packages -- the same shape `@object-ui/layout`
had before #3787. `packages/plugin-aggrid` no longer exists at all. The
remaining 19 entries do resolve and therefore do work.
The new gate test pins both faces, discovering the hosts rather than
hardcoding four, since the bug was a host nobody remembered to add.
@vercel

vercelBot commented Aug 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectuiIgnoredIgnoredAug 9, 2026 1:31pm

Request Review

…mputing it
No behaviour change: the describe body already computes the host list for
the zero-hit guard, so the parameterised case can take that array rather
than walking apps/site/app a second time.
@yinlianghuiClaude

Copy link
Copy Markdown
CollaboratorAuthor

验收通过(objectui 分片 PM,session session_01GTRjn8xBqp75dk7kFupVRt)#3904(v17)

实物核验:head 5288f211c,两提交 3 文件。CI 亲读终态:18 检查全 completed、0 失败。要点:死条目判定读了 Next 16 源码两处消费点而非照抄 issue(MODULE_NOT_FOUND vs ERR_PACKAGE_PATH_NOT_EXPORTED 的区分 + 反向确认余 19 项有效);CHANGELOG「有意加的」矛盾主动查证并以 556/556 预渲染 + Build Docs 干净环境绿收口;发现式枚举 4 宿主逐一断言;无浏览器的验证层级(静态断言 + 构建差分,差分标记因 page-header 字符串假阳改用三个注册独有标记)如实declared。守界(未碰 packages/layout)。finding #3944(根 vitest alias 四死条目)持有待分诊。


Generated by Claude Code

@yinlianghui
yinlianghui marked this pull request as ready for review August 9, 2026 13:46
@yinlianghui
yinlianghui added this pull request to the merge queueAug 9, 2026
Merged via the queue into main with commit 137a112Aug 9, 2026
19 checks passed
@yinlianghui
yinlianghui deleted the claude/issue-3904-playground-layout-reg branch August 9, 2026 13:46
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

apps/site: Playground 未注册 layout 组件(输入 page-header 得红色错误面板);transpilePackages 还列着两个非依赖包

2 participants

@yinlianghui@claude