fix(console): type-check tsconfig.node.json and wire it into the gate (#3305) - #3383
Merged
Merged
Conversation
…#3305) apps/console/tsconfig.node.json is the project covering vite.config.ts, and nothing ran it: `build` is `tsc && vite build && …`, and plain `tsc` reads tsconfig.json without building project references. The file deciding how the console is bundled was the one file in the app no gate read, and it had accumulated 7 standing errors (5 at the issue's baseline, plus 2 more from scripts/vite-maplibre-worker.ts landing since). Three defects, fixed at their source: - `compression({ algorithm })` -> `algorithms: [...]`. The singular key is not in vite-plugin-compression2's ViteCompressionPluginOption and was never read at runtime either; it fell through to the plugin default, which is BOTH `['gzip', 'brotliCompress']`. So each of the two instances compressed every asset twice. The .gz/.br pair that made the build look correct came from the default, not from these options. Artifact set is unchanged (449 .gz + 449 .br, byte-identical file list before and after); the duplicated work is gone. - scripts/vite-*.ts were unresolvable from this project (TS6307 + TS2307). They stay in scripts/ — a deliberate root-level location the root vitest project already covers via `scripts/**/*.test.ts` — and instead the root package.json now declares the `vite` it imports, matching how it already declares console's other Vite plugins (vite-plugin-compression2, rollup-plugin-visualizer). Root and apps/console resolve the identical vite@8.2.0 install, so `Plugin` stays one type. - `defineConfig` now comes from `vitest/config`, so the `test` block (merged into vitest.config.ts) is typed instead of falling outside UserConfigExport. Wiring, which is the point of the issue: console's `type-check` now also runs `tsc -b tsconfig.node.json --force`. `--force` is load-bearing — without it the build-mode up-to-date check skips the project when only dependencies changed, which silently reported green while `vite` was unresolvable. The project emits to a gitignored cache dir rather than `noEmit`, because tsconfig.json references it and a referenced project that disables emit is TS6310; left at the default it littered .js/.d.ts beside every input. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
…3305) Wiring the tsconfig.node.json project into `type-check` is only half a gate if `pnpm type-check` can serve a cached green for it. `type-check` declared no `inputs`, so turbo hashed only each package's own files — and the project this gate added reads `scripts/vite-*.ts`, which live at the repo root, inside no package. Measured before this change: breaking `scripts/vite-crypto-stub.ts` left `@object-ui/console:type-check` on the identical hash 9b56b04fee5b19cc, "cache hit, replaying logs", turbo exit 0 — while running the same script directly reported TS2322. CI restores a turbo cache across runs (`restore-keys: turbo-${{ runner.os }}-type-check-`), so that stale green was reachable there, not just locally. With `$TURBO_ROOT$/scripts/vite-*.ts` added to the task's inputs, the same experiment gives a different hash (14b3af20777c366d), "cache miss, executing", and turbo exit 1 with the real error; restoring the file returns a cache hit on the original hash. `$TURBO_DEFAULT$` is listed first so nothing is narrowed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
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 free
to 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 #3305
复核:premise 成立,且错误已从 5 条涨到 7 条
Issue 的基线是
f44d8727f,当前origin/main(0554e889c)重跑,7 条:多出的 2 条来自 issue 提出后新落的
scripts/vite-maplibre-worker.ts—— 正好实证了 issue 里那句预判:「任何住在scripts/的共享 vite 插件都会继承这个问题」。没门禁的文件会持续吸附新错误。一处需要更正 issue 的判断:
algorithm在运行时也是失效的Issue 说「实证 build 仍产 .gz 与 .br,所以运行时认这个键,属类型/运行时错位」。读已安装的
vite-plugin-compression2@2.5.3运行时源码,这个归因是错的:algorithm(单数)根本不在解构列表里,从头到尾没被读过。两份.gz/.br不是因为运行时认了这个键,而是因为它落到了默认值 —— 而默认值是两个算法都做。也就是说这两个 plugin 实例各自都在做 gzip + brotli,每个产物被压了两遍。旧 build 日志里dist/vite.svg.br连续出现两次就是这个重复的痕迹。结论不变(该修),但性质不是「类型说错了、运行时是对的」,而是两端都错,只是默认值恰好掩盖了它。修完每个实例只做自己那一个算法,重复功耗消失。
三个问题的修法
algorithm→algorithms: [...],以已安装插件声明的键为准。scripts/vite-*.ts的类型解析路径 —— 选择「留在scripts/,补声明」而不是搬走。理由:scripts/是本仓刻意维护的仓库级 TS 代码位置(rootvitest.config.mts的unitproject 显式 include 了scripts/**/*.test.ts,那里现有 6 个测试文件);而 rootpackage.json本来就替 console 声明着vite-plugin-compression2和rollup-plugin-visualizer。所以补一条 rootvitedevDependency 是顺着既有约定走,搬文件反而要连带搬测试、动 root vitest 的 include。已核验 root 与 apps/console 解析到同一份vite@8.2.0(realpath 相同),Plugin不会裂成两个类型。defineConfig改从vitest/config导入 ——vite.config.ts的test块确实是活的(apps/console/vitest.config.ts用mergeConfig合了进去),而vitest.config.ts自己早就是从vitest/config导入的,这里只是对齐。接线(本单主交付)—— 两层,少一层就是假绿
第一层:console 的 type-check 真的跑这个 project
走
apps/console/package.json的type-check,即 CIci.yml里pnpm type-check的既有挂点,不新增 workflow。--force是有承载作用的,不是保险丝。 我第一版写的是不带--force的tsc -b,反向验证第 4 例(删掉 root 的vite解析)时它报了绿 —— build 模式的 up-to-date 检查认为项目没变就整个跳过了。只有输入文件变化时才重跑,依赖变化会假绿。加--force后同一例正确变红。第二层:turbo 的缓存 key 必须覆盖
scripts/vite-*.ts第一层写完后我去验第二层,发现接了等于没接。
type-check任务没声明inputs,turbo 只按各 package 自己目录下的文件算 hash;而这道门禁读的scripts/vite-*.ts在仓库根、不属于任何 package。实测(改动前):
CI 是跨 run 恢复 turbo 缓存的(
restore-keys: turbo-${{ runner.os }}-type-check-),所以这个假绿在 CI 上同样可达,不只是本地现象。修法是给任务补
inputs($TURBO_DEFAULT$放第一位,不收窄任何既有行为):改动后同一实验:
这是本 PR 唯一一处超出 issue 文件面的改动(
turbo.json一处inputs),属于接线本身的必要组成 —— 不补这层,第一层的门禁在 CI 上可以被缓存整个跳过。验证
门禁绿:
反向验证(防再腐)—— 预期方向事先声明:门禁就是一个编译器直接编译这几个文件,不存在计数/反转的微妙情况,五例都应当变红:
algorithms退回algorithmdefineConfig退回从vite导入../../scripts/vite-*.tsvite解析scripts/vite-crypto-stub.ts,经turbo run type-checkinputs前是绿,见上)全部按预期变红,恢复后基线
EXIT=0。.gz/.br 双产物实证(PM 要求): 分别用修前(
algorithm)与修后(algorithms)各跑一次vite build,对产物清单做 diff:产物集合完全不变,双算法照常产出;变化的只是不再压两遍。
测试:
实现细节:为什么不是
noEmittsconfig.json引用了这个 project,而被引用的 project 不许noEmit(TS6310,实测会把现有的tsc --noEmit一起打红)。保持默认又会在每个输入旁边吐.js/.d.ts(apps/console/vite.config.js、scripts/vite-*.d.ts),这堆未跟踪垃圾本身就是它当初难以接进门禁的原因之一。因此outDir指向 gitignore 覆盖的node_modules/.cache/tsc/console-node,并显式写rootDir: "../.."(composite会把rootDir默认成本文件所在目录,导致../../scripts/*.ts越界 TS6059)。关于 changeset
未附 changeset,按 AGENTS.md「功能改进需写 changeset;纯 bug 修复不需要」。本 PR 无任何用户可见变化 —— 构建产物集合已实证逐字节相同,改动全部落在类型门禁与构建工具链上;而 objectui 是 39 包 fixed 组联动发布,为纯工具链改动推一次全组版本并不合适。如果维护者希望留一条发布记录,我再补一个 patch changeset。
附带发现(未在本 PR 修,已另开 issue)
configLoader: 'native'drops — a future Vite major turns 5 warnings into a broken config load #3384 — console 的 vite/vitest 配置依赖configLoader: 'native'将要移除的能力(__dirname、无扩展名的相对 import),现在只是警告,Vite 下个 major 翻默认值时会变成配置加载失败。apps/console/tsconfig.node.jsonincludesvitest.setup.ts, which does not exist #3385 —apps/console/tsconfig.node.json的 include 一直列着vitest.setup.ts,但该文件不存在(console 的 setup 是../../vitest.setup.dom.tsx)。死路径,无害,按最小改动原则未顺手删。