发现于 #3899 的实现(PR #3940 ),不在该 PR 处理 —— 那一单的面被 PM 裁决明确收窄为 packages/layout 一个包的清单。这一条是仓级 gate 的缺口,是另一类事实。
机制 #3899 是这样被发现的:一个人在做别的事时顺手注意到 packages/layout/package.json 声明 "sideEffects": false,而 src/index.ts 靠加载期 registerLayout() 注册六个组件 key。实测(PR #3940 正文有数据):纯副作用引入 import '@object-ui/layout'; 在遵守该 flag 的打包器下产出 0 字节 bundle、零注册、退出码 0、无警告;故障远端才现形为红色 Unknown component type 面板(OBJUI-001)。
PR #3940 修了 layout,并加了一条构建级 pin(packages/layout/src/__tests__/side-effects-manifest.test.ts)。但那条 pin 是包内作用域的 —— 它读 packages/layout/package.json、探 layout 自己的入口形态。下一个包重犯同样的错,仓里没有任何东西会变红。
这与 #3663 / #3647 是同一形状的缺口:files 声明与磁盘的漂移也曾靠人手工逐包 diff 才发现(一周内两次),随后才有了 scripts/__tests__/package-files-exist.test.ts 这条派生式仓级 gate。sideEffects 现在正处在「靠人顺手发现」的阶段。
今天的普查(origin/main @ 230ffd8 ,逐包核实) "sideEffects": true —— packages/components、packages/fields。诚实(且最保守)。"sideEffects": false —— packages/core、packages/i18n、packages/layout(PR fix(layout): declare the load-time registration in sideEffects (#3899) #3940 修正中)、packages/react-runtime、packages/sdui-parser、packages/types。除 layout 外逐个查过 barrel 的顶层语句,均无加载期副作用 ,因此今天都是诚实的(react-runtime 的 barrel 是 src/index.tsx,注意别被 index.ts 的 glob 漏掉)。字段缺省(undefined)—— 其余全部,含所有 plugin-*。这是安全默认值:打包器会假定有副作用。PluginLoader 动态 import 的那批包因此从未暴露在这个风险里。 所以除 layout 之外目前没有第二个活的缺陷 。这也是本条按 observation-class 归档、不打 pm:queue 的原因。
为什么仍然值得记下来 缺口不是「有没有当前受害者」,而是这类谎言无声 。它的三个属性叠在一起正好躲开所有现有检查:
构建全绿、无警告 —— 打包器认为自己在执行你的声明,不是在报错。 只有 sideEffects: false(或数组漏掉某个入口形态)+ 加载期副作用同时 成立才发作,两半分别看都无可指摘。 现有消费者只要同时 import 了具名导出,模块就一定被求值 —— 缺陷因此可以潜伏任意长时间。packages/layout: sideEffects: false contradicts the load-time registerLayout() — a side-effect-only import can be tree-shaken away #3899 明确写了「今天没人被打到是巧合,不是设计」。 一个新包(或在现有 false 包里新加一处加载期注册/注册表写入/全局赋值)就能原样重演,且没有任何红灯。
可能的处置(供分诊,未实施) 在 scripts/__tests__/ 加一条派生式仓级 gate,形状照 package-files-exist.test.ts:遍历 workspace 每个包,对声明了 sideEffects: false 或数组的包,检查其 barrel(含 .ts/.tsx 两种拼写)是否存在顶层副作用语句(裸调用、注册表写入、globalThis 赋值);数组情形另检查是否覆盖 main/module/exports 指向的全部 JS 入口形态。PR #3940 里的推导函数(resolvableEntryPaths())与真打包器探针(含 sideEffects: false 对照,防止 gate 在打包器不摇时空绿)可以直接上提复用,layout 的包内 pin 随之收敛为仓级 gate 的一个 specimen。
⚠️ 一处别踩的坑,PR #3940 实测过:发布路径不是唯一的消费面 。apps/console/vite.config.ts:122 与 examples/console-starter/vite.config.ts 都把 @object-ui/layout alias 到 packages/layout/src,打包器对这些源文件读的是同一份 package.json;只声明 dist/* 时 console 的 alias 形态依然产出 0 字节 bundle。任何仓级 gate 都必须把 workspace alias 入口一并算进「入口形态」,否则它会给一个仍然会炸的包发绿灯。
退出条件 上述仓级 gate 落地(本条即完成);或 出现第二个实际发作的包 —— 那时这条就不再是 dormant,应升级为具体缺陷。 参考位置:scripts/__tests__/package-files-exist.test.ts(同形状的派生式仓级 gate 先例)、packages/layout/src/__tests__/side-effects-manifest.test.ts(PR #3940 的包内 pin,可上提的推导与探针)。
关联:#3899 (发现于此)、#3663 / #3647 (files 字段的同形状缺口与它的 gate)。
发现于 #3899 的实现(PR #3940),不在该 PR 处理 —— 那一单的面被 PM 裁决明确收窄为
packages/layout一个包的清单。这一条是仓级 gate 的缺口,是另一类事实。机制
#3899 是这样被发现的:一个人在做别的事时顺手注意到
packages/layout/package.json声明"sideEffects": false,而src/index.ts靠加载期registerLayout()注册六个组件 key。实测(PR #3940 正文有数据):纯副作用引入import '@object-ui/layout';在遵守该 flag 的打包器下产出 0 字节 bundle、零注册、退出码 0、无警告;故障远端才现形为红色Unknown component type面板(OBJUI-001)。PR #3940 修了 layout,并加了一条构建级 pin(
packages/layout/src/__tests__/side-effects-manifest.test.ts)。但那条 pin 是包内作用域的 —— 它读packages/layout/package.json、探 layout 自己的入口形态。下一个包重犯同样的错,仓里没有任何东西会变红。这与 #3663 / #3647 是同一形状的缺口:
files声明与磁盘的漂移也曾靠人手工逐包 diff 才发现(一周内两次),随后才有了scripts/__tests__/package-files-exist.test.ts这条派生式仓级 gate。sideEffects现在正处在「靠人顺手发现」的阶段。今天的普查(origin/main @ 230ffd8,逐包核实)
"sideEffects": true——packages/components、packages/fields。诚实(且最保守)。"sideEffects": false——packages/core、packages/i18n、packages/layout(PR fix(layout): declare the load-time registration insideEffects(#3899) #3940 修正中)、packages/react-runtime、packages/sdui-parser、packages/types。除 layout 外逐个查过 barrel 的顶层语句,均无加载期副作用,因此今天都是诚实的(react-runtime的 barrel 是src/index.tsx,注意别被index.ts的 glob 漏掉)。undefined)—— 其余全部,含所有plugin-*。这是安全默认值:打包器会假定有副作用。PluginLoader动态 import 的那批包因此从未暴露在这个风险里。所以除 layout 之外目前没有第二个活的缺陷。这也是本条按 observation-class 归档、不打
pm:queue的原因。为什么仍然值得记下来
缺口不是「有没有当前受害者」,而是这类谎言无声。它的三个属性叠在一起正好躲开所有现有检查:
sideEffects: false(或数组漏掉某个入口形态)+ 加载期副作用同时成立才发作,两半分别看都无可指摘。sideEffects: falsecontradicts the load-timeregisterLayout()— a side-effect-only import can be tree-shaken away #3899 明确写了「今天没人被打到是巧合,不是设计」。一个新包(或在现有
false包里新加一处加载期注册/注册表写入/全局赋值)就能原样重演,且没有任何红灯。可能的处置(供分诊,未实施)
在
scripts/__tests__/加一条派生式仓级 gate,形状照package-files-exist.test.ts:遍历 workspace 每个包,对声明了sideEffects: false或数组的包,检查其 barrel(含.ts/.tsx两种拼写)是否存在顶层副作用语句(裸调用、注册表写入、globalThis赋值);数组情形另检查是否覆盖main/module/exports指向的全部 JS 入口形态。PR #3940 里的推导函数(resolvableEntryPaths())与真打包器探针(含sideEffects: false对照,防止 gate 在打包器不摇时空绿)可以直接上提复用,layout 的包内 pin 随之收敛为仓级 gate 的一个 specimen。apps/console/vite.config.ts:122与examples/console-starter/vite.config.ts都把@object-ui/layoutalias 到packages/layout/src,打包器对这些源文件读的是同一份package.json;只声明dist/*时 console 的 alias 形态依然产出 0 字节 bundle。任何仓级 gate 都必须把 workspace alias 入口一并算进「入口形态」,否则它会给一个仍然会炸的包发绿灯。退出条件
参考位置:
scripts/__tests__/package-files-exist.test.ts(同形状的派生式仓级 gate 先例)、packages/layout/src/__tests__/side-effects-manifest.test.ts(PR #3940 的包内 pin,可上提的推导与探针)。关联:#3899(发现于此)、#3663 / #3647(
files字段的同形状缺口与它的 gate)。