chore(deps): upgrade phase 4 — pnpm 11, TS 6, ESLint 10, React 19 - #19
Merged
Merged
Conversation
pnpm 11 stops reading package.json#pnpm and every non-auth .npmrc key, so a bare version bump would silently drop all 49 security overrides and shamefully-hoist. - overrides, shamefullyHoist, autoInstallPeers, strictPeerDependencies move to pnpm-workspace.yaml; .npmrc keeps only the registry guidance - allowBuilds records the existing decision explicitly: core-js, core-js-pure, es5-ext and esbuild postinstalls stay disabled (pnpm 10 already skipped them; 11 fails the install until each is decided) - Dockerfile copies pnpm-workspace.yaml before the frozen install, otherwise the lockfile no longer matches the (missing) overrides - lockfile stays lockfileVersion 9.0, unchanged byte for byte pnpm 11.27.1 rather than 12.x: 12 is a Rust rewrite shipped as native per-platform optional dependencies (released 2026-08-26); the pnpm 10 self-switch to it fails locally with ENOEXEC because the exe placeholder only becomes a binary through a postinstall that pnpm skips. The 11 line self-switches cleanly and carries the same config model. note: minimumReleaseAge (default 1 day) rejects tinymce 8.9.2 until 2026-09-24T01:25Z; `pnpm run` re-verifies the lockfile, so scripts and the pre-commit hook fail in that window too. Verified with pnpm_config_minimum_release_age=0.
6.0 is the last release with the JavaScript compiler API. The project tsconfig (umi's generated bundler-mode config, no baseUrl) hits none of the 6.0 deprecations; typecheck, lint and the organize-imports prettier plugin all run clean on it. TypeScript 7 stays out: its package entry only exports `version`, and typescript-eslint (latest 8.70.1) peers on typescript <6.1.0. As a probe, `npx -p typescript@7.0.2 tsc --noEmit` checks this codebase with zero errors in 1.35s (5585 files) - ready once the lint toolchain catches up.
@umijs/max pins ESLint 8.35 (EOL 2024-10), typescript-eslint 5 and stylelint 14 behind `extends: @umijs/max/eslint` and `max lint`. ESLint 9 is EOL as well (2026-08-06), so the target is ESLint 10. - eslint.config.mjs ports the umi recommended rule set one to one (core, react, rules-of-hooks, typescript) plus the project overrides; jest rules on test files map to @vitest/eslint-plugin; typescript-eslint 8 replacements for the removed ban-types / no-empty-interface. Probed with a planted file: every rule family still fires - eslint-plugin-react / jsx-a11y peer on ESLint <=9 but run clean on 10 (they only use context APIs that 10 kept); peer warnings accepted - stylelint.config.mjs ports the umi stylelint preset (standard, css-modules, no-ignored-properties, postcss-less for .less); stylelint-config-prettier is obsolete since formatting rules are gone. import-notation is `string` because Tailwind v4 only resolves string @imports; lint:style now also covers tailwind.css - new findings fixed rather than silenced: d3 callbacks declare their `this` type (no-invalid-this), three unused catch bindings dropped (caughtErrors defaults to all in v8); media-feature-range-notation is pinned to `prefix` for .less - umi's bundled Less fails on `(width <= 768px)` with "Missing closing ')'" (caught by a build) - lint-staged uses --no-warn-ignored; .eslintignore folds into the flat config ignores; the import guard no longer mistakes rule names like 'vitest/no-mocks-import' for imports
With every source import declared (repo-hygiene gate) and the lint toolchain now a direct dependency, the flat hoisted layout is no longer needed - node_modules top level now holds only the declared packages instead of every transitive one, so an undeclared import fails the same way on every machine instead of resolving by accident. - check-dist-secrets resolves @cesium/engine's Ion.js through the cesium package (it is cesium's dependency, not ours); its test does the same - the mock loadability test reaches @umijs/preset-umi along the @umijs/max -> umi chain; the hygiene allowlist shrinks to react and react-dom (umi-provided by design) verified without hoisting: typecheck, ESLint 10, stylelint, 59 tests, production build (sizes identical), dist secret scan, dev server with MFSU across 24 routes plus calendar/table/signature/PDF/Cesium/OL interaction checks
umi 4.7 aliases react/react-dom to the project's own copies and mounts
through createRoot, so React 19 is a direct dependency now (19.3.0 is
what ships in the framework chunk).
- @pansy/react-amap is gone: its Marker goes through @pansy/use-portal,
which calls unmountComponentAtNode - removed in React 19 - and the
library has not been published since 2024-06. The AMap page talks to
JS API 2.0 directly (map, click-to-place marker, destroy on unmount)
and keeps @pansy/amap-api-loader, which is React-free, so the
no-AMAP_KEY fallback behaves exactly as before
- antd 5 static methods mount via ReactDOM.render; the official
@ant-design/v5-patch-for-react-19 is loaded first thing in app.tsx
(drop it together with an antd 6 upgrade)
- react-pdf 11 requires React 19 and suspends by default; the PDF page
opts out with suspense={false} to keep its onLoadError alert.
pdfjs-dist follows to 6.3.289 exactly (hygiene gate); cmaps and
standard_fonts keep their paths, the worker path is unchanged
- @types/react 19: useRef needs an initial value, RefObject<T> now
carries null
- eslint-plugin-react keeps an explicit version: its 'detect' path calls
context.getFilename(), which ESLint 10 removed (hard crash)
verified: 17 pages pixel-identical to phase 3; 24 routes with zero
console errors (no React 19 warnings); AMap click places a marker and
unmount is clean; PDF renders 2 pages; calendar/table/signature/dnd/OL
interactions pass; size gate passes (entry 762 KB of 780, login 764 of
780, home 1204 of 1250 gzip)
|
Warning Review limit reachedNext included review available in 43 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (25)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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.
背景
依赖升级 阶段 4:pnpm 11、TypeScript 6、ESLint 10 / stylelint 17、React 19。以阶段 3(
chore/deps-phase3)为 base。改动
pnpm 10 → 11.27.1
package.json#pnpm和.npmrc中鉴权以外的配置。直接升版本会让 49 条安全 overrides 和提升配置静默失效。因此:pnpm-workspace.yaml.npmrc只保留 registry 说明allowBuilds显式记录 core-js、es5-ext、esbuild 的安装脚本不执行(与 pnpm 10 下的实际行为一致)pnpm-workspace.yaml,否则 lockfile 与缺失的 overrides 对不上lockfileVersion 9.0,内容逐字节不变关闭 shamefullyHoist
TypeScript 5.9 → 6.0:6.0 是最后一个带 JS 编译器 API 的版本。TS 7 暂缓,因为 typescript-eslint 最新版的 peer 为
<6.1.0。实测 TS 7.0.2 对本项目做类型检查:0 错误,耗时 1.35 秒。ESLint 8 → 10,stylelint 14 → 17(脱离 @umijs/lint 预设)
eslint.config.mjs逐条移植 umi 的推荐规则集:stylelint.config.mjs移植 umi 的 stylelint 预设this类型;去掉 3 个未使用的 catch 变量version: 'detect'下会调用 ESLint 10 已删除的context.getFilename()而直接崩溃,版本号已写死.less固定使用前缀写法React 18 → 19(umi 4.7 会把 react 别名到项目自己安装的版本;产物 framework chunk 中确认为 19.3.0)
@pansy/react-amap移除:它的 Marker 调用了 React 19 已删除的unmountComponentAtNode,且该库 2024-06 之后没有再发布。高德页改为直接调用 JS API 2.0;加载器仍用不依赖 React 的@pansy/amap-api-loader,所以未配置 key 时的行为不变ReactDOM.render挂载,React 19 已删除该 API,因此加载官方的@ant-design/v5-patch-for-react-19suspense={false},保留原来由onLoadError驱动的告警useRef必须传初始值;RefObject<T>的类型现在包含 null验证
pnpm check、build:github、pnpm size、产物秘钥扫描全部通过;audit 为 0 high / 4 moderate / 1 low需要注意
--config.confirm-modules-purge=false。从本分支切回旧分支时同样需要重装chore/deps-phase4-antd6-experimental,未推送。功能上已通过,但 umi 的布局模板需要改走 v3 的 API,且 D3 频率图会溢出卡片,尚未修复