遗留系统迁移
迁移首先不是技术热情,而是经营现实
遗留系统迁移最容易被讲成:
- 老系统太烂了
- 新框架更先进
- 迟早都要迁
这些话有时会抓到一点事实。
但它们都不够成为决策依据。
一个更成熟的起点应该是:
遗留系统迁移首先是业务和工程经营问题,其次才是技术栈变化问题。
因为迁移这件事的代价,往往远大于很多人一开始的想象。
它不是一个“项目任务”。
它更像一次长期组织动作。
什么叫“遗留系统”
遗留系统不等于旧技术。
这是第一个必须讲清楚的点。
一个系统即使技术栈新,如果:
- 没人敢改
- 依赖关系不清
- 改一处坏三处
- 发布风险极高
它在工程意义上依然是遗留系统。
反过来,一个技术栈老一点的系统,如果:
- 边界清晰
- 团队熟悉
- 变更可预测
它未必是当前最急迫的“遗留问题”。
所以“遗留”真正说的是:
系统的维护风险和演进摩擦。
不只是年份。
第一问永远不是“迁到什么”,而是“为什么现在迁”
很多失败迁移,失败不是因为技术路线完全错了。
而是开始得太草率。
成熟团队会先问:
- 现在最大的痛到底是什么
- 这个痛是结构性问题还是局部工程问题
- 不迁会怎样
- 迁了会怎样
如果回答不清楚这些问题,迁移计划通常会越来越像“技术愿望清单”。
什么情况下迁移是合理的
比较常见的合理信号包括:
- 维护成本持续上升
- 新功能开发效率明显下降
- 招聘和培养成本过高
- 关键依赖已经停止维护
- 安全风险持续扩大
- 当前架构已明显限制未来能力
这里最重要的是“持续”。
不是一次发布很痛,就说明一定要迁。
而是问题已经成为系统性趋势。
ROI 为什么不能只看开发速度
很多人做迁移评估,最容易只看一个维度:
新系统开发会不会更快。
这当然重要。
但迁移 ROI 至少还应包括:
- 稳定性收益
- 安全收益
- 招聘收益
- 培训收益
- 发布复杂度变化
- 未来架构空间
否则很容易高估短期好处,低估迁移期摩擦。
最危险的误区:把“重写”当成默认迁移路径
很多团队一提迁移,就直接想到:
推倒重来。
这通常是最危险的默认反应。
不是因为重写永远不行。
而是因为重写意味着你在做两件极难的事:
- 同时重建功能
- 同时重建系统
这会把风险叠加。
所以成熟团队更常见的思路是:
渐进替换。
先把最糟糕、最痛、最值得先动的部分拆出来。
Strangler Fig 为什么是迁移讨论里的经典比喻
Martin Fowler 的 Strangler Fig Application 之所以经常被引用,是因为它提供了一种更现实的迁移心智。
重点不是一次切走所有旧系统。
而是让新系统逐步包裹、替代旧系统,直到旧系统自然退场。
这个思路的价值在于:
- 可以分阶段验证
- 可以降低一次性风险
- 更容易和业务并行推进
它不是一种技术实现。
更像一种迁移哲学。
共存期为什么才是真正的主战场
很多迁移计划都把“最终态”写得很好看。
但真正消耗团队的,通常是中间态。
也就是:
新旧系统必须长期共存的阶段。
在这个阶段,团队会面对很多真实问题:
- 路由谁管
- 登录态怎么共享
- 样式如何不互相污染
- 埋点怎么统一
- 发布节奏怎么协调
- Bug 归因怎么做
如果这些问题没提前设计好,迁移会变成长期痛苦,而不是可控过渡。
常见迁移路线到底在交换什么
jQuery 到 React / Vue
这类迁移经常不是“语法升级”。
它本质上是在把 DOM 命令式思维迁移到组件和状态驱动思维。
真正难的不是 JSX。
而是:
- 状态归属重新定义
- DOM 直接操作习惯切断
- 页面初始化方式改造
AngularJS 到 Angular / React
这种迁移常常伴随:
- 模板体系变化
- 依赖注入心智变化
- 路由和状态管理重构
所以它更像系统迁移,不只是框架替换。
CRA 到 Vite / Next.js
这类迁移表面看轻。
但也可能牵扯:
- 构建配置
- 环境变量
- 路由与部署方式
- SSR 可能性
它不一定最难,但也不该被低估。
Class Components 到 Hooks
这通常适合渐进进行。
但重点不是“语法现代化”。
而是借机整理:
- 状态逻辑
- 副作用边界
- 组件职责
为什么迁移最怕“功能升级”和“架构升级”绑死在一起
这是很多迁移计划失败的常见原因。
团队会想:
- 既然要迁,不如顺便重做交互
- 既然要迁,不如顺便改数据层
- 既然要迁,不如顺便统一设计系统
结果就是:
本来已经很难的系统替换,被绑上了一整车额外目标。
成熟做法通常是:
尽量拆开目标。
先保证迁移本身可控,再决定哪些能力值得第二阶段优化。
团队为什么常常低估“知识迁移成本”
遗留系统不只是代码旧。
它往往还承载了很多隐性知识:
- 旧业务规则
- 特殊边界条件
- 发布顺序习惯
- 历史兼容 hack
这些知识很多时候不在文档里。
而是在老成员脑子里。
所以迁移计划如果只看代码量,不看知识承载,就很容易踩坑。
这也是为什么迁移往往需要:
- 访谈老成员
- 梳理历史异常逻辑
- 做旧系统行为基线
为什么“先建立可观察性”常常比“先写新代码”更重要
如果团队连旧系统到底:
- 慢在哪里
- 错在哪里
- 哪些页面最关键
- 哪些功能最常改
都没有数据,迁移顺序往往就是拍脑袋。
所以一个成熟的迁移步骤通常会先补:
- 监控
- 错误追踪
- 关键路径埋点
- 页面和模块使用数据
这样迁移才有优先级依据。
中国互联网语境里为什么遗留系统迁移特别常见
中国互联网很多系统都有这些背景:
- 业务涨得快
- 历史活动页和运营系统堆积
- 多年迭代后技术栈断层
- 多端混杂
- 老 H5、老中后台、新框架并存
在这种环境里,遗留系统迁移不是少数派话题。
它几乎是大团队的常态工程问题。
所以中国语境下的迁移,通常更强调:
- 分阶段
- 风险可控
- 不影响业务节奏
- 新旧共存能力
海外语境里为什么迁移更容易和平台演进一起讨论
海外很多产品,尤其是 SaaS 和平台型业务,更容易把迁移和这些目标放在一起看:
- 更好的可维护性
- 更好的测试性
- 更清晰的架构边界
- 逐步现代化
这使得迁移讨论更常与:
- Strangler Fig
- modularization
- incremental modernization
这类语言绑定在一起。
所以海外语境里,迁移往往更强调“渐进现代化”而不是“大重写”。
迁移过程中最常见的坏味道
坏味道一:因为技术厌倦而启动迁移
“我们受够这个旧栈了”可以是真情实感。
但不能单独成为决策依据。
坏味道二:没有中间态设计
只画目标态,不画共存期。
这种方案通常最危险。
坏味道三:缺少退出计划
如果试点失败怎么办?
如果某个子系统迁到一半卡住怎么办?
这些都该提前想。
坏味道四:只迁代码,不迁团队能力
如果团队没有真正掌握新体系,迁移完也只是把问题换了一种形式。
面试或技术分享里怎么讲更成熟
一个更成熟的表达可以是:
遗留系统迁移首先是业务和工程经营问题,不是技术热情问题。关键不只是迁到什么,而是为什么现在迁、迁移期怎么共存、风险最高的边界在哪里,以及团队是否准备好承接新系统的长期维护。
最稳妥的迁移思路通常不是一次性重写,而是通过 Strangler Fig 这类渐进替换方式,把最高价值、最高痛点的部分优先迁出,并在整个过程中补上可观察性、行为基线和团队能力转移。
实践建议
实践一:给一个真实旧系统写迁移前评估
不要急着给方案。
先写清:
- 为什么迁
- 不迁会怎样
- 哪些是最高痛点
- 哪些其实可以先不动
实践二:画一张共存期架构图
重点不是目标态,而是新旧系统一起活着时:
- 路由怎么接
- 登录态怎么共享
- 埋点怎么统一
- 样式怎么隔离
实践三:挑一个低风险模块做 Strangler Fig 试点计划
用它验证:
- 团队协作方式
- 发布节奏
- 回滚机制
- 行为差异是否可控