多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

react-spring 从 Yarn 3 Berry 迁移到 pnpm:一份 65 项任务清单的拆解、执行策略与仓库落地证据

react-spring 从 Yarn 3 Berry 迁移到 pnpm:一份 65 项任务清单的拆解、执行策略与仓库落地证据 react-spring 从 Yarn 3 Berry 迁移到 pnpm一份 65 项任务清单的拆解、执行策略与仓库落地证据【免费下载链接】react-spring✌️ A spring physics based React animation library项目地址: https://gitcode.com/gh_mirrors/re/react-springreact-spring 仓库在specs/001-migrate-to-pnpm/目录下完整保留了一次典型的 Monorepo 包管理器迁移工程档案以 tasks.md 为执行主体配套 plan.md、spec.md、research.md、quickstart.md 以及两份命令契约文档。这篇技术文章以 tasks.md 的 8 个阶段、65 项任务T001–T065为骨架逐阶段解读其任务编排逻辑、依赖关系与验证策略并用当前仓库中已经落地的配置文件、CI 工作流与基线审计数据印证迁移的最终状态。读完本文你可以掌握如何用基线采集 → 发现式安装 → 幽灵依赖修复 → 按用户故事验证 → 抛光收尾的方法论组织一次包管理器迁移pnpm 严格隔离模式下pnpm-workspace.yaml、packageManager锁定、pnpm.onlyBuiltDependencies、.npmrc的最小化配置如何落地以及如何用pnpm pack产物对比来证明发布物与迁移前等价。一、迁移背景与工程档案结构react-spring 原使用 Yarn 3 Berryyarn3.8.7nodeLinker: node-modules即通过扁平 hoist 树模拟传统 node_modules 布局。plan.md 给出的迁移目标概括为用 pnpm 严格隔离的node_modulespnpm 默认布局替换 Yarn 的 hoisted 布局让每个 workspace 只能看到自己声明的依赖工作区清单从根package.json的workspaces字段迁移到pnpm-workspace.yaml重写所有与 yarn 耦合的根脚本、5 个 GitHub Actions 工作流和 5 个下游消费侧 fixture严格隔离暴露出的幽灵依赖phantom dependencies必须在迁移 PR 内补齐声明已发布包的打包内容必须与迁移前保持等价对应 spec 中的 FR-015 / SC-005。spec.md 定义了 4 个用户故事US1 贡献者本地流程、US2 CI 全绿、US3 changesets 发布流程、US4 parallax E2E和 7 条可量化成功标准SC-001 至 SC-007tasks.md 就是围绕这些故事与标准展开的任务分解。tasks.md 开头的组织约定值得注意任务格式为[ID] [P?] [Story] 描述[P]表示操作不同文件、不依赖未完成任务可并行执行每项任务必须指明确切的文件路径或目录该迁移的测试就是既有测试套件本身当时的 Jest 单测、tsc --noEmit、Cypress E2E——不新增测试文件验证任务直接运行既有套件。说明tasks.md 的日期上下文是 2026-05 的仓库状态spec 中记录 Node 22.15.0、CI 矩阵 Node 18/20、Jest Cypress 测试栈。当前仓库已在此之后继续演进如 specs/002-vitest-browser-migration/ 将测试栈换成 Vitest browser 模式、specs/003-remix-to-react-router-7/ 将文档站从 Remix 迁移到 React Router 7本文涉及差异处会分别标注迁移时点与当前仓库。二、任务总览8 个阶段与执行顺序tasks.md 将 65 项任务编排为 8 个阶段其中阶段 0–2 是跨故事的前置条件阶段 3–6 一一对应 US1–US4阶段 7 是收尾阶段任务区间定位关键产出Phase 0 基线采集T001迁移前在干净next分支记录 yarn 侧时间/产物基线baseline.md 各 workspace 的.tgz对照包Phase 1 SetupT002–T004引入 pnpm 配置面与 yarn 配置并存pnpm-workspace.yaml、.npmrc、根package.json改造Phase 2 FoundationalT005–T027发现式安装、幽灵依赖修复、清除 yarn 残留pnpm-lock.yaml、删除yarn.lock/.yarnrc.yml/.yarn/Phase 3 US1 贡献者流程T028–T040全新克隆可 install/build/test/lint/dev重写后的根脚本与文档Phase 4 US2 CIT041–T0555 个工作流 5 个 publish-ci fixture 迁 pnpm/npm全绿 CIPhase 5 US3 发布T056–T059changesets 流程 dry-run pack 等价性每个发布包 PASS/DIFF 记录Phase 6 US4 E2ET060parallax E2E 套件跑通E2E greenPhase 7 PolishT061–T065文档清扫、grep 断尾、warm-cache 验证、基线脚手架拆除审计记录保留临时产物删除tasks.md 的Dependencies Execution Order一节给出了一张精确的依赖图Phase 0 必须最先完成且不可并行Phase 2 中 T005首次安装 发现问题必须先完成T006–T021 的幽灵依赖修复可全部并行T022 再安装、T023 提交 lockfileT024–T027 清理任务可并行US1 与 US2 互为独立可并行US3 依赖 US1 和 Phase 0 的基线包US4 只依赖 Phase 2Phase 7 依赖全部完成其中 T064 还要求 CI 缓存积累至少 3 次运行。执行策略部分给出了三种走法MVP first只做到 US1 就停下来验证此时本地开发已完整迁移、CI 还在 yarndiff 依然可评审、增量交付Phase 0 → US1 开 draft PR → US2 → US3 → US4 → Polishsquash 合并、并行团队策略坦承这种强耦合迁移基本是单作者工作唯一值得拆分的并行点是 T006–T021 的幽灵依赖修复和 T049–T053 五个同构的 fixture 迁移。三、Phase 0先留下可证伪的对照组T001T001 是整个迁移中约束最强的一条任务文档原文用CRITICAL标注必须在任何 pnpm 改动触碰仓库之前、在一份干净的next分支检出上无node_modules、无.pnpm-store完成否则 SC-001/002/003/005 这些时间/等价性标准将不可证伪unfalsifiable。它要求采集冷/热 yarn install 耗时time yarn install --immutable删node_modules后重测yarn build-ci、yarn test:ts、yarn test:unit的耗时对每一个对外发布的 workspacepackages/与targets/下package.json不含private: true的目录执行yarn pack把 tarball 存入specs/001-migrate-to-pnpm/baseline/workspace.tgz并把解包文件列表与name/version/exports/main/module/types/files字段写入baseline.md这些基线产物随迁移分支提交作为迁移后的对照物最终在 T065 删除。当前仓库中保留着这一阶段的审计产物baseline/_baseline.json 记录了迁移时点 12 个发布 workspace 的完整 pack 数据——每个包的 11–13 个文件清单、关键package.json字段、tarball 字节数与 pack 耗时例如react-spring/core为 12 个文件、119760 字节、约 238ms这正对应 T001 要求的文件列表 关键字段基线。这个 JSON 文件本身就是 T059 pack 等价性对比的数据来源。四、Phase 1pnpm 配置面的最小化落地T002–T004Phase 1 的目标是双轨并存引入 pnpm 配置但不拆除 yarn 配置拆除留给 Phase 2三个任务互不依赖、可并行。T002pnpm-workspace.yaml只写活着的四个 globT002 要求根目录创建pnpm-workspace.yaml内容严格取 research.md R-002 确认的四个存活 globpackages/*、targets/*、demo、docs并明确不要包含packages/parallax/react-spring/parallax-demo——该目录在磁盘上已不存在是 Yarn Berry 时代容忍下来的死条目而 pnpm 会对缺失的 workspace 路径告警/报错顺势清掉。当前仓库的 pnpm-workspace.yaml 与任务描述完全一致packages: - packages/* - targets/* - demo - docsT003根package.json的三处改动T003 规定(a) 整段移除workspaces字段(b)packageManager从yarn3.8.7换成当时最新的 pnpm 9.x(c) 新增pnpm.onlyBuiltDependencies数组种子列表为[swc/core,cypress,esbuild,remix-run/dev,parcel/watcher,core-js,core-js-pure]。同时刻意不动任何脚本体和 devDependencies——脚本重写在 Phase 3 的 T029/T030。这里的设计依据来自 research.md R-001/R-003packageManager字段 Corepack 是 pnpm 的标准锁定路径与 Yarn 3 当时用packageManager.yarn/releases/的约定对等能消除lockfile 漂移类 CI 抖动而 pnpm 9 默认拦截依赖的 postinstall 构建脚本必须显式放行swc/core、esbuild等需要本地构建的原生包否则装上了但跳过构建步骤运行时才会爆。当前 package.json 的状态印证了这一设计packageManager: pnpm9.15.9, pnpm: { onlyBuiltDependencies: [ parcel/watcher, swc/core, core-js, core-js-pure, es5-ext, esbuild ] }可见放行清单在迁移完成后又随依赖栈演进收敛过cypress/remix-run/dev已随测试栈与文档栈的后续迁移退出仓库新增了es5-ext——这与 tasks.md Notes 中最终列表由安装时的 ignored-build-script 告警决定的说明一致。T004.npmrc只放 registry坚守严格隔离T004 要求 .npmrc只包含registry 锁定一行且明确禁止预置node-linkerhoisted或任何public-hoist-pattern条目——spec 的Resolution mode一节认为把 hoist 垫片搬过来等于把现有技术债锁死违背迁移初衷。只有当 T005 发现确实无法修复的个案时才允许补 hoist 规则。当前仓库的.npmrc内容就是一行registryhttps://registry.npmjs.org/严格隔离策略一直保留到了今天的开发者指引 CLAUDE.mdnode_modules是非 hoist 的workspace 只能 import 自己package.json里声明的包遇到Cannot find module foo去补依赖声明不要加 hoist 规则。五、Phase 2发现式安装与幽灵依赖修复T005–T027这是整个迁移中工程判断密度最高的阶段tasks.md 同样以CRITICAL标注在 Phase 2 完成前任何用户故事工作都不允许开始。2a 发现式安装T005T005 的动作很朴素启用 Corepack 后跑第一次pnpm install完整捕获所有输出——每一条 Module not found、每一条 An import-name-required dep is missing 警告、每一条 ignored build script 提示。这一步被明确定性为 discovery pass发现趟后续 T006–T021 都是对它的响应。research.md R-006 给出了预期暴露面的预判表targets/three可能缺react-three/fiberpeer 声明、targets/konva/zdog缺渲染库 peer、packages/core需确认reactpeer、docs需确认 Remix dev 依赖等。2b 幽灵依赖修复T006–T021全部 [P]T006–T021 共 16 项任务逐一对应一个 workspace 的package.jsoncore、animated、shared、rafz、types、parallax、mock-raf、eslint-config、react-spring 伞包、targets 下的 web/native/three/konva/zdog、demo、docs。tasks.md 对此有一个很值得借鉴的规范如果 T005 对某 workspace 报告零问题任务也要标记完成并在 PR 里写明 no changes required——Notes 一节强调确认过没有缺失声明本身就是验证结果而不是静默跳过。这避免了任务清单在评审时被误读为没做。每项任务的判断流程固定为读该 workspace 当前package.json→ 与 T005 的错误/警告输出交叉比对 → 把缺失项补进dependencies或peerDependencies。docs 那条T021额外要求验证remix-run/dev的 postinstall 在 pnpm 下仍会触发因为根目录有一个postinstall: remix setup node依赖它。2c 收口 lockfile 与清理T022–T027T022重跑pnpm install并迭代 T006–T021直到安装零ERR_PNPM_*错误、且没有未解释的 ignored build script 警告只放行真正需要构建的依赖T023提交生成的pnpm-lock.yamlT024–T026删除yarn.lock、.yarnrc.yml、整个.yarn/目录releases/plugins/cache——对应 spec 的 FR-009要求所有 Yarn 3 Berry 专属产物在迁移提交中移除T027更新.gitignore移除.yarn/*、!.yarn/patches等 Berry 模式保留标准 pnpm 模式node_modules。Phase 2 的 Checkpoint 验收语写得很具体严格隔离的pnpm-lock.yaml已存在、无 yarn 残留、且能从干净状态跑通pnpm install --frozen-lockfile。当前仓库中pnpm-lock.yaml存在于根目录而yarn.lock、.yarnrc.yml、.yarn/均已不存在说明该 Checkpoint 已达成。六、Phase 3US1 贡献者流程迁移T028–T040US1 的独立测试定义就是验收标准本身在全新克隆上依次执行pnpm install --frozen-lockfile、pnpm build、pnpm test:ts、pnpm test:unit、pnpm lint、pnpm prettier:check全部成功且 test commit 时 pre-commit hooks 正常触发。脚本体重写T028–T030三个任务分别处理根package.json中三组脚本体重写依据是 contracts/developer-commands.md 的命令映射契约。该契约还立了一条不变量脚本名不许变只改脚本体——有肌肉记忆的贡献者照常工作。核心映射包括动作迁移前迁移后锁定安装yarn install --immutablepnpm install --frozen-lockfile指定 workspace 跑脚本yarn workspace name cmdpnpm --filter name cmd根目录加依赖yarn add pkg -Wpnpm add -w pkg查依赖为什么被装yarn why pkgpnpm why pkg需要重写脚本体的条目及其前后形态引自同一契约文档脚本迁移前脚本体迁移后脚本体docs:devyarn workspace react-spring/docs devpnpm --filter react-spring/docs devdemo:devyarn workspace react-spring/demo devpnpm --filter react-spring/demo devtestyarn test:ts yarn test:unit yarn test:e2epnpm test:ts pnpm test:unit pnpm test:e2etest:e2estart-server-and-test yarn vite serve packages/parallax/test --host … yarn cypress runstart-server-and-test pnpm vite serve packages/parallax/test --host … pnpm cypress runreleaseyarn clean yarn yarn build …pnpm clean pnpm install pnpm build …当前 package.json 中可以看到这些脚本体的 pnpm 形态已经落地例如docs:dev为pnpm --filter react-spring/docs dev、release为pnpm clean pnpm install pnpm build pnpm changeset publish --no-git-tag测试栈换成 Vitest 后test:ts/test:unit步骤后来从 release 链上调整了位置这是迁移完成后的后续演进。验证与计时任务T031–T037T031–T037 是一组把验收场景跑一遍并留痕的任务干净克隆安装US1 场景 1、Husky hooks 触发验证T032 要求真实造一个 noop commit 确认 pre-commit 的 Prettier 检查与 commit-msg 的 commitlint 都执行然后git reset --soft HEAD~1回退对应 FR-008、time pnpm build/time pnpm test:ts/time pnpm test:unit三次计时并写入baseline.md对应小节T033–T035服务于 SC-001、lint 与 prettier 干净确认T036、docs:dev与demo:dev双 dev server 启动并确认可服务内容T037验证完杀掉进程。Husky 的兼容性依据在 research.md R-004prepare是标准 npm 生命周期钩子pnpm 与 yarn 一视同仁地执行husky install本身不依赖包管理器唯一要做的是验证。当前根package.json中prepare: huskyHusky 9 的简化调用形式保留着这条链路。文档同步T038–T040T038 要求把 README 的安装/使用说明替换为 quickstart.md 的内容T039 要求更新 CLAUDE.md 中 Stack 一节的包管理器描述和 Common commands 表T040[P]清扫docs/目录 markdown 中所有 yarn 引用。current 仓库的 CLAUDE.md 第一条 Stack 即为Package manager: pnpm 9.15.9 with strict isolated node_modules (default). Pinned via packageManager … activated through Corepack说明 T039 已完成。七、Phase 4US2 CI 全量迁移T041–T055US2 的规模是5 个工作流 5 个消费侧 fixture重写依据是 contracts/ci-commands.md。标准安装块顺序即约束契约文档给出了替换所有cache: yarnyarn install --immutable组合的标准块- name: Checkout repo uses: actions/checkoutv4 - name: Setup pnpm uses: pnpm/action-setupv4 # 无需 version 输入 —— pnpm/action-setup 从 package.json 的 packageManager 读取 - name: Setup node ${{ matrix.node || 20 }} uses: actions/setup-nodev4 with: node-version: ${{ matrix.node || 20 }} cache: pnpm - name: Install run: pnpm install --frozen-lockfile这里有一个容易踩的顺序陷阱被显式强调Setup pnpm 必须排在 Setup node 之前因为actions/setup-node的cache: pnpm需要 pnpm 已在 PATH 上。缓存 key 自动从pnpm-lock.yaml的 SHA 派生无需手写key:pnpm 全局 storeLinux runner 上位于~/.local/share/pnpm/store/v3由 setup-node 负责缓存。逐工作流、逐步骤的重写映射T041–T048 覆盖checks.ymllint/prettier 步骤、bundle-size.ymlyarn build --filter!react-spring/docs→pnpm build --filter!react-spring/docs、tests.yml的 build / test-unit / test-types 三个 job包括 test-types 中yarn add typescript${{ matrix.ts }}→pnpm add -w typescript${{ matrix.ts }}这种往工作区装特定版本工具链的写法、experimental.yml与nightly.yml均为 install 块 build-ci的简单形态。契约还规定了重读的推荐顺序checks面最小先验证安装块→ bundle-size → tests面最大含 paths-filter→ experimental/nightly模式照搬。两个特殊任务T046paths-filtertests.yml的 changes job 中把yarn.lock换成pnpm-lock.yaml、把.github/publish-ci/**/yarn.lock换成.github/publish-ci/**/package-lock.json其余过滤条目packages/**、targets/**、.github/workflows/*.yml等不变。这是换包管理器但别漏了触发条件这类细节的典型代表。T049–T053publish-ci fixture全部 [P]五个下游消费侧 fixturecra5、next、vite、node-standard、node-esm每个都是模拟终端消费者的独立小项目research.md R-005 的决策是把它们迁到 npm 而不是 pnpm——fixture 里装的是构建 job 产出的package.tgz用哪个包管理器与 react-spring 正确性无关而 npm 随 Node 自带、且每个 Node 版本都有能减少 CI 中包管理器表面积。T054 则把test-published-artifactjob 的每一步改成 npmnpm uninstall react-spring/web、npm install ./web/package.tgz …、npm info npm ls、npm run build、npm test它显式声明依赖 T049–T053fixture 必须已经是 npm。当前仓库中.github/publish-ci/下每个 fixture 目录都已含package-lock.json如 .github/publish-ci/next/package-lock.json且.github/workflows/下bundle-size.yml、checks.yml、experimental.yml、nightly.yml、tests.yml等文件内容均含 pnpm 调用印证 T041–T054 已落地。仓库后续又新增了docs-deploy.yml、release.ymlcra5fixture 在后续清理中移除均属迁移完成后的演进。T055 是 US2 的收尾验证推送迁移分支、在 PR 上确认五个工作流全过并把每个 job 的冷安装耗时记入baseline.md的 CI cold install (pnpm)对照 yarn 基线SC-002。八、Phase 5US3 发布流程与 pack 等价性证明T056–T059US3 的独立测试是pnpm changeset→pnpm vers→ 完整pnpm release到实际 publish 前一步为止版本正确 bump、构建与测试通过、每个发布 workspace 的 tarball 与迁移前基线一致。T056真实跑一次pnpm changeset并加一个chorechangeset 记录迁移本身验证交互流程能生成.changeset/name.mdT057跑pnpm vers验证所有版本锁定version-locked包 bump 到同一目标版本然后git restore复原T058跑pnpm release到changeset publish之前验证clean → install → build → test:ts → test:unit链路连续成功T059是迁移的硬证明任务对每个发布 workspacepackages/、targets/下package.json不含private: true的目录执行pnpm pack解包后与 T001 产生的baseline/workspace.tgz逐一比对 (a) 文件列表 (b)name/version/exports/main/module/types/files字段。判定规则写得非常精确生成元数据内部的空白与顺序差异可容忍其他任何差异都是必须在合并前解决的缺陷并逐 workspace 把 PASS/细节记录到baseline.md的 Pack equivalence 小节。当前仓库的 baseline/_pack-diff.json 正是 T059 的机器化结果12 个 workspace 中 11 个verdict: PASS文件数完全一致、字段无 diff唯一的DIFF出现在packages/parallax——pnpm 打包少了 1 个文件package/test/README.mdyarn 侧 13 个文件 vs pnpm 侧 12 个。这类一个测试目录的 README 是否该进包的差异正是 T059 设计出来要人工裁决的粒度也说明该机制真实地拦截到了细微的发布物差异。九、Phase 6 与 Phase 7E2E 收尾与抛光T060–T065T060US4单任务收尾从一次全新pnpm install出发跑pnpm test:e2e确认 Vite dev server 在 3000 端口对packages/parallax/test起服务、Cypress 无头启动、parallax.cy.ts通过。tasks.md 特意解释了为什么 E2E 优先级只给 P3当时 E2E 只在本地跑CI job 被注释掉失败不阻塞合并——但它覆盖的正是更严格的模块解析可能悄悄引入的那类回归所以必须保绿。当前仓库中该 E2E 已由后续迁移改为 Vitest browser 模式入口为tests/e2e/parallax.spec.tsx对应根脚本pnpm test:e2e。Phase 7 的五项任务构成长尾清扫 拆除脚手架T061[P]清扫packages/*/README.md与targets/*/README.md中的 yarn 引用T062全仓库grep -rn yarn --include*.md --include*.yml --include*.yaml --include*.json --include*.sh逐一解决非历史性changelog/releases命中另点名检查scripts/、.changeset/、根.eslintrc*/tsconfig*。这条服务 SC-007100% 的仓库级文档从yarn …更新为 pnpm 等价命令T063最终端到端计时删node_modules后跑 quickstart 全流水线install --frozen-lockfile → build-ci → test:ts → test:unit → package → test:e2e每步计时并追加到baseline.md的 End-to-end pipeline (pnpm)断言冷安装流水线总耗时 ≤ 迁移前同款的 110%SC-001 的可执行版本;T064等 PR 上至少 3 次 CI 运行后检查actions/setup-nodev4cache: pnpm的缓存命中率与 warm 安装耗时对照 yarn warm 基线SC-003若不达标要么调pnpm-lock.yaml缓存 key要么在 PR 描述中如实记录并接受回归——不硬压数据T065合并前拆除基线脚手架删除specs/001-migrate-to-pnpm/baseline/下的对照 tarball临时物保留测量记录本身作为 SC-001/002/003/005 的审计痕迹。tasks.md Notes 一节把这条生命周期又强调了一遍tarballs are deleted; the measurements are the audit trail。十、Notes任务清单背后的工程纪律tasks.md 末尾的 Notes 是整份文档方法论的浓缩值得单独提炼[P] 的严格定义不同文件、不依赖未完成工作才允许并行幽灵依赖任务允许是 no-opT006–T021 中若某 workspace 本来就声明齐全任务照样存在并确认无缺失后完成——确认过不等于跳过了按逻辑组提交Phase 0 → 1 → 2 → 每个用户故事各一个提交点使 git history 可以按任务粒度评审全程禁用--no-verify迁移本身也不能绕开 Husky hooks否则 FR-008 的验证就是自我欺骗hoist 规则的最小化授权如果 T022 暴露出一个真正无法修复的幽灵依赖比如某第三方包 import 了未声明的 peer允许在.npmrc加定向的public-hoist-pattern[]exact-pkg并内联写明原因但明令禁止放宽成public-hoist-pattern[]*——一条通配 hoist 等于宣告迁移失败。十一、当前仓库的最终状态核对把 tasks.md 的验收点与当前仓库实际文件对照可以确认迁移已完整落地并持续演进tasks.md 验收点当前仓库证据T002 四个 glob 的 workspace 清单pnpm-workspace.yaml 逐行一致T003packageManager锁定 onlyBuiltDependenciespackage.jsonpnpm9.15.9 6 项放行清单T004.npmrc仅 registry、无 hoist 规则.npmrc 单行registryhttps://registry.npmjs.org/T023–T027 lockfile 与 yarn 产物根目录存在pnpm-lock.yamlyarn.lock/.yarnrc.yml/.yarn/不存在T028–T030 脚本体 pnpm 化package.json 中docs:dev/demo:dev/test/release均为pnpm调用T039 CLAUDE.md 文档更新CLAUDE.md Stack 首条 完整 pnpm 命令表 严格隔离说明T041–T053 CI 与 fixture.github/workflows/各 yml 含 pnpm 安装块.github/publish-ci/各 fixture 持有package-lock.jsonT001/T059 基线与 pack 等价审计baseline/_baseline.json、baseline/_pack-diff.json11 PASS / 1 DIFF需要说明的两点适用前提其一tasks.md 中引用的部分文件路径如packages/eslint-config、targets/konva、targets/zdog、targets/native、packages/react-spring伞包、cra5fixture是迁移时点的仓库结构当前仓库已经历后续重构这些目录已调整其二任务文档中的绝对路径/Users/josh.ellis/code/react-spring/...是作者本机检出位置读者应理解为其指向本仓库对应相对路径。十二、方法论小结这份 tasks.md 给出的可复用范式可以概括为五步先造对照组Phase 0任何等价性声明先有基线数据才有意义基线产物随迁移分支提交、验证完成后拆除临时物但保留测量记录双轨过渡再收口Phase 1→2新旧配置短暂并存用一次发现式安装把问题全部逼出水面再按文件粒度并行修复、统一收口 lockfile、一次性清除旧残留以用户故事为单位验证Phase 3–6每个故事都有独立测试定义和 CheckpointMVP 只做 US1 也能形成可评审、可回退的中间态命令契约化把每个 yarn 命令对应什么 pnpm 命令写成契约文档contracts/developer-commands.md、contracts/ci-commands.md脚本体、CI step、文档清扫全部对照执行保证迁移不留半 yarn 半 pnpm的死角用产物而不是口述证明等价T059/T063pnpm pack的文件列表 关键字段 diff、端到端流水线计时断言≤110% 基线、CI 缓存命中率观察把迁移没弄坏东西变成可复跑的检查项。对于任何维护 Turborepo/pnpm workspaces 的 TypeScript Monorepo 的仓库这套基线 → 发现 → 修复 → 故事化验证 → 审计留痕的编排方式以及严格隔离优先、hoist 规则最小授权的取舍原则都是可以直接搬走的工程实践。【免费下载链接】react-spring✌️ A spring physics based React animation library项目地址: https://gitcode.com/gh_mirrors/re/react-spring创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表