Dev diagnostics: attribution cost checks (WIDE_SCOPE_DEPS at 30) now on by default via performance tracks, and count HMR plumbing
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 新手友好度
- 45/100
- Issue 类型
- 缺陷
- 描述清晰度
- 基本清楚
- 活跃度
- 活跃
- 技术栈
- javascript, typescript
- 领域
- devtools, performance
调研方向
Start with packages/signals/src/core/attribution.ts, especially checkDepWidth and the wideDeps threshold, then read packages/solid/src/refresh/index.ts to trace the _plumbing memos. Compare that behavior with the performance-tracks attribution holder and decide which documented diagnostic behavior should apply. Done means the default dev session no longer produces an unintended warning, or the intended default and coverage are clearly established.
由索引模型根据 Issue 内容生成。
描述
Summary
Since @solidjs/vite-plugin loads the Chrome Performance panel tracks in every dev session (next.47), the attribution engine is enabled by default in dev with its cost checks on. WIDE_SCOPE_DEPS — designed as an opt-in close-up lens at a threshold of 30 — now fires on ordinary code. The first case found isn't even user code: it counts the HMR wrapper's plumbing memos.
Reproduction
examples/hackernews-spa on @solidjs/[email protected], pnpm dev, load any 30-story feed page:
[WIDE_SCOPE_DEPS] effect "effect" is subscribed to 30 sources — it re-runs when any of them change.
Narrow its reads or split it into smaller memos. Sources: anonymous, anonymous, anonymous, …
in <Document> › body.children › <App> › <Router> › … › <Stories> › effect › effect
The same app on plugin next.35 is silent (attribution was not enabled there).
What the 30 sources are
<For> itself tracks only the list (mapArray returns one accessor). The sources come from dev-only HMR:
- In dev,
$$component(solid-js/refresh) wraps every component instance, andHMRCompreturns acreateMemo(..., { _plumbing: true, transparent: true })instead of the component's node (packages/solid/src/refresh/index.ts). - Each of the 30
<Story>rows is therefore a memo accessor, not an<li>. - The
<For>sits in aninsertwith noname(henceeffect › effect); its inner effect normalizes the mapped array, calling every function it finds under tracking → 30 plumbing memos.
In production Story returns its <li> and the insert tracks nothing per row. Tracking the memos is correct (the insert must follow them for a hot swap), but the wrapper's comment says plumbing memos are "unrecorded by the attribution engine", while checkDepWidth (packages/signals/src/core/attribution.ts) counts every dep, plumbing included.
Why it now shows by default
- The threshold never moved:
wideDeps: 30since the prototype (1386b9c31) and #3018 (3d2c21fe8), whose docs describe it as: "fires at a much lower threshold, but only while the attribution engine is enabled — it names the offending sources.HUGE_FAN_INis the always-on backstop for the pathological case."HUGE_FAN_INisGRAPH_SIZE_WARN_AT = 2000(packages/signals/src/core/dev.ts). - Performance tracks (#3580) take a hold with
attribution.enable({ log: false, ...options.attribution })and leavechecksat the engine default (true); the adapter's own comment says to passchecks: false"for records only". @solidjs/vite-pluginnext.47 imports the tracks module into every dev client entry (performanceTracksdefaults on underserve).
Net effect: the opt-in lens became an always-on default-dev warning at a threshold calibrated for someone already looking.
Options (not mutually exclusive)
- Tracks don't take the cost checks — the performance-tracks hold passes
checks: false(records only, as its comment describes).WIDE_SCOPE_DEPSstays the opt-in lens it was designed as. Behavior change: all five cost checks (hotRuns,hotTime,wideDeps,unstableMemos,wideWrites) go quiet in default dev unless another holder asks for them. - Raise the default (≈1000) if the cost checks are meant to be default-on now. Then
WIDE_SCOPE_DEPSandHUGE_FAN_IN(2000, always on) largely overlap and the case for two separate checks weakens. - Exclude
_plumbingsources from the width count regardless of the threshold — HMR plumbing shouldn't count against a scope, at any size. Worth auditing the other per-source attribution checks for the same gap.
All three are dev-diagnostics behavior changes (@solidjs/signals, @solidjs/web).
Possibly related (unverified)
examples/chat on the same plugin logs repeated ABANDONED_FLIGHTS ("computed" abandoned 3 flights in 1000ms) under <App> › <For> › <Loading> › children › <Reply> › computed › computed while a reply streams — each streamed chunk supersedes the previous pending value. <Reply> also goes through the HMR wrapper, so this may be the same plumbing blind spot or a separate calibration problem for streamed sources; not traced yet.
- 主要语言
- TypeScript
- 星标
- 36.2k
- 派生
- 1.1k
- 平均合并
- 11 小时
- 30 天内合并 PR
- 343
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
solidjs/solid 的其他 Issue
-
`lazy()`: remounting an already-loaded component renders empty (or the Suspense fallback) since 1.9.14可能已有人在做 @itisrmk 于 8 天前认领。 未关闭1.x
难度 2/5 1-3 小时 新手友好度 62/100
维护者通常 1 天内回复
-
难度 4/5 3-5 天 新手友好度 56/100
维护者通常 1 天内回复
-
enhancement
难度 5/5 一周以上 新手友好度 35/100
维护者通常 1 天内回复
-
`createRoot`'s dispose function keeps `fn` alive, so `<For>`/`<Index>` rows retain removed list items可能已有人在做 @boombang 于 10 天前认领。 未关闭1.x
难度 4/5 1-2 天 新手友好度 45/100
维护者通常 1 天内回复
-
Keep element state when the runtime moves a node (`moveBefore()` and not detaching what is re-inserted)可能已有人在做 关联的 PR 仍在进行中或已合并。 未关闭enhancement
难度 5/5 一周以上 新手友好度 35/100
维护者通常 1 天内回复
相似的 Issue
-
freshness freshness:observed-only
难度 2/5 1-3 小时 新手友好度 68/100
thoroc/context-radar#282 ·
-
bug P2 rust
难度 2/5 1-3 小时 新手友好度 82/100
维护者通常 1 天内回复
-
area: web
难度 2/5 1-3 小时 新手友好度 85/100
gabe-santana/arkdraw#25 ·
-
bug require-triage
难度 2/5 1-3 小时 新手友好度 72/100
expressjs/expressjs.com#2549 · 1 个 reaction ·
维护者通常 1 天内回复
-
bug good first issue hacktoberfest
难度 2/5 1-3 小时 新手友好度 88/100
codercops/discord-bot#101 · 1 条评论 ·
维护者通常 1 天内回复