大版本升级
升级主版本依赖或框架(如 React 17→18、Node 16→18)且不让生产环境崩溃。
为什么
大版本携带破坏性变更,即使编译通过也会在运行时悄悄出错 — 移除的 API、变更的默认行为、新增的必填配置。跳过大版本会累积债务:等得越久破坏性变更堆得越多,一次跨 3 个大版本远比三次跨 1 个大版本危险。旧大版本的生态支持会下降(安全补丁、库兼容),所以保持当前也是安全姿态。有纪律的大版本升级是计划 内、可回滚、经审查的事件 — 不是周五下午的惊吓。
何时使用
当前大版本距 EOL 6-12 个月内,或你需要的功能只在新大版本中。安排在低流量周,绝不在发布冻结期。
如何做
1. 通读 CHANGELOG / 迁移指南;列出所有触及你代码的破坏性变更 2. 从 main 拉分支:git checkout -b upgrade/react-18 3. 在 package.json 升版本,跑 install,捕获所有类型检查/lint 错误 4. 先用 codemod:用官方 codemod(如 npx @codemod/cli)做机械重命名,再手动改 5. 逐文件修剩余破坏,每个修复单独提交以便二分定位 6. 跑完整测试套件 + e2e;为 changelog 中行为变更的部分补测试 7. 至少部署 staging 一个完整业务周期;监控错误率和关键指标 8. 有 feature flag 或金丝雀则分批发布;保持旧版本热备以便即时回滚
示例
# React 17 -> 18 升级
git checkout -b upgrade/react-18
npm install react@18 react-dom@18
npx tsc --noEmit # 暴露类型错误
# Codemod:把 ReactDOM.render 替换为 createRoot
npx @codemod/cli --plugin react-18-upgrade src/
# 手动:更新 index.tsx
- import { render } from "react-dom"
+ import { createRoot } from "react-dom/client"
- render(<App/>, document.getElementById("root"))
+ createRoot(document.getElementById("root")!).render(<App/>)
# 验证 StrictMode 双调用不会破坏 effect
npm test && npm run e2e常见问题
- ⚠一次跨多个大版本(如 16→18)— 破坏性变更相互叠加,无法判断哪个升级导致哪个失败。
- ⚠只信类型检查 — 运行时行为变更(新 StrictMode 双调用、事件池变更)通过类型却破坏 effect。
- ⚠漏掉传递依赖:升 React 18 但 @testing-library/react 留在 12 会导致测试悄悄失败。
- ⚠周五部署丢失回滚窗口 — 若周一出问题,无法区分是升级还是周末其他变更。
最佳实践
- ✓一次升一个大版本,中间各跑一轮测试+staging — 三次跨 1 大版本比一次跨 3 大版本更省。
- ✓维护一个"升级待办"看板:changelog 中每条破坏性变更都成一张工单,不遗漏。
- ✓用 feature flag 在开关后发布升级,运行时出问题可秒级回滚无需重新部署。
- ✓升级安排在 Q1/Q2,绝不在 Q4(假期冻结)或重大发布前一周 — 给自己留回滚跑道。