跪拜 Guibai
← All articles
Frontend

A Weekend-by-Weekend Vue 2 to Vue 3 Migration That Actually Shipped

By 柯克七七 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Vue 2 reaches end of life at the end of 2023, forcing thousands of teams to migrate. This field report shows that automated tooling solves less than a third of the work, and the real cost is in manually untangling scattered component logic and fixing silent runtime behavior changes like the `.sync` modifier removal.

Summary

A legacy Vue 2 backend with no TypeScript and four former maintainers was upgraded to Vue 3, TypeScript, and Vite over three weekends. The migration tool only handled 30% of the work; the rest required manual rewrites of the Options API to Composition API, router upgrades, and a state-management shift from Vuex to Pinia. A missed `v-model` behavior change in Vue 3 broke a form submission, underscoring that migration guides must be checked line by line, not from memory.

Adding TypeScript exposed practical friction: optional interface props break templates, `ref(null)` infers the wrong type, and older libraries need custom `.d.ts` shims. The payoff was immediate — IDE autocomplete finally worked across the entire codebase. Engineering improvements in the final weekend added auto-formatting on commit, component auto-imports, and environment variable management that replaced hardcoded API addresses.

When a neighboring team needed the same upgrade, they copied the configuration directly, valuing a working setup over polished alternatives. The core takeaway is that effective frontend tooling isn't about novelty; it's about guardrails that let the least experienced team member produce acceptable code.

Takeaways
Automated migration tools solved only 30% of the Vue 2 to Vue 3 upgrade; the rest required manual rewrites.
Converting Options API to Composition API demands untangling logic scattered across data, computed, and methods before changing any syntax.
Vue 3 removed the `.sync` modifier, silently changing `v-model` behavior and breaking form submissions if not caught.
`ref(null)` infers as `Ref<null>` and must be explicitly typed as `ref<User | null>(null)` to accept object assignments later.
Optional properties in a TypeScript interface for props will cause template errors; use `PropType` or `withDefaults` instead.
Custom `.d.ts` shim files are still necessary for older third-party libraries that lack `@types` packages.
Component auto-imports with `unplugin-vue-components` require explicit resolution when custom component names collide with UI library components.
Extracting hardcoded API addresses and keys into `.env` files eliminated the need for full releases when configuration changed.
Conclusions

The gap between official migration guides and real-world codebases is wide: the guide won't tell you that four previous developers left four different coding styles, and that untangling those styles is the actual bottleneck.

A working, imperfect configuration that a colleague can copy immediately has more organizational value than a polished, documented solution they won't read.

The metric for good frontend tooling isn't technical sophistication but whether it prevents the weakest team member from shipping broken code.

Concepts & terms
`.sync` modifier removal in Vue 3
Vue 2's `.sync` modifier allowed two-way binding on a prop. Vue 3 removed it and unified the behavior under `v-model`, which can now accept an argument (`v-model:propName`). Code that relied on `.sync` will silently fail after migration.
Pinia
The officially recommended state management library for Vue 3, replacing Vuex. It offers full TypeScript inference without extra type declarations and a simpler API without mutations.
`unplugin-vue-components`
A Vite plugin that automatically imports Vue components when they are used in templates, eliminating manual import statements. Requires explicit configuration when component names conflict across libraries.
From the discussion

The loudest objection is that a solo, unannounced production refactor is reckless: no milestones, no stakeholder sync, no test coverage, and the refactorer alone absorbs the risk while the company reaps the benefit. A counterpoint emerges in a reply — the work was split into four PRs with rollback plans and the schedule was confirmed with the boss. A second current runs through the thread: the refactor is seen as scab behavior that eliminates maintenance work for others and could lead to layoffs once the system needs fewer people. Several comments dismiss the effort as busywork that AI could handle in an hour, while a few quieter voices acknowledge the planning required to ship in three weekends and note that AI-assisted refactoring changes the cost equation.

A production refactor without a standardized plan, milestones, stakeholder sync, or full regression testing is irresponsible and shifts all risk onto the individual.
The refactor was not done in secret — the schedule was confirmed with the boss, changes were split into four PRs, and each had a rollback plan.
Refactoring a legacy system that multiple developers have touched risks breaking unknown edge cases and buried landmines; if the system is not critical, refactoring is acceptable, but business logic should be left alone.
Solo weekend refactoring is scab behavior: it eliminates maintenance work for colleagues and can lead to headcount reduction once the system requires fewer maintainers.
With AI tools, a Vue 2 to Vue 3 migration is trivial — some claim it can be done in an hour with almost no bugs, making manual weekend refactors pointless.
Component-based splitting improves maintainability, but without unit test coverage, future iterations will still introduce problems.
Refactoring is often abandoned halfway in organizations; finishing in three weekends indicates solid planning.
AI-assisted refactoring changes the economics: what took three weekends before may now take one, with the developer focusing on architecture while AI handles boilerplate.
Featured comments
取名困难群众 57 likes hot

Your passion for technology is something I acknowledge, but if I met a colleague like this I would stay far away. Reasons: 1. No standardized plan or milestones, relying purely on personal experience and enthusiasm. What if the schedule slips? What if you hit a technical bottleneck? 2. Even if the refactor only changes structure and not logic, problems can still arise: edge cases, compatibility issues — were these communicated with QA? Did all test cases pass? 3. The whole process was never synced with management or the team; solo operation. 4. What happens if issues arise after going live? Was there a contingency plan? Support personnel? Who takes accountability? This kind of work — donating credit to the company while keeping all the risk for yourself — is only suitable for personal demo projects, not production systems. These are just some of my immature thoughts. Hope they give you a little food for thought.

柯克七七  · 1 likes

😊 Thank you for your thoughtful comment. I'll do a proper retrospective on this 👍

派森585  · 1 likes

No problem.

沉默不语 24 likes hot

Great, another pot to carry. You refactor on your own overtime, and later every bug in this project will basically be yours to own.

潍坊中登_被辞退在家打码版  · 1 likes

Haha

柯克七七

Haha, that risk is real, so I confirmed the schedule with my boss before the refactor — I didn't do it in secret 😂 And I split the changes into four PRs, each with a rollback plan. If bugs do appear, the whole team shares the blame, not just me. Ah, whatever, hahaha

ToCodex_AI 2 likes

The hardest part of a refactor isn't the code itself — it's pushing it forward without affecting the business. Finishing in three weekends shows good planning. Component-based splitting does improve maintainability a lot, but without matching unit test coverage, subsequent iterations will still easily bury landmines.

See top comments, translated →
Source: juejin.cn ↗ Google Translate ↗ Backup ↗