Vue.js

Vapor Mode is now the default renderer for new Vue components

VUE

Vue's Vapor Mode moved from experimental to production-proven on our render-heavy dashboards last year, the kind of internal tooling with enough live-updating widgets on screen at once that the old virtual DOM overhead was genuinely visible to users as jank rather than just a number in a benchmark. This year, with the remaining ecosystem gaps largely closed, it became the default renderer for new components rather than something we opted into deliberately for specific performance-sensitive cases.

The performance ceiling for Vue apps has moved up noticeably as a result, most visibly on exactly the kind of screen that motivated our first cautious adoption: dashboards with dozens of independently updating data points, where the old rendering model's overhead scaled poorly as the number of reactive bindings on screen grew. Vapor Mode's compile-time approach to reactivity sidesteps a meaningful chunk of that overhead, and on our busiest internal dashboard the difference between the old and new renderer was large enough that engineers noticed it without being told to look for it.

The mental model shift the migration required a couple of years ago now barely registers for developers joining the team fresh, since they're simply writing components against the current default rather than consciously choosing a newer rendering mode over an established one. That's a nice inversion from how the early adoption period felt, when using Vapor Mode meant explaining to a new team member why this particular component looked slightly different from the rest of the codebase and what tradeoff justified the difference.

The ecosystem gaps that held up broader adoption for a while were mostly in third-party component libraries that assumed the older rendering internals, and closing them took patience rather than any clever workaround, mostly waiting for library maintainers to catch up and occasionally contributing a fix ourselves when a library we depended on heavily hadn't gotten there yet. Now that the gaps have closed, there isn't really a remaining case where we'd deliberately choose the old renderer for a new component, which is exactly the point at which a migration stops being a project and starts being just how things work.

Migrating existing components rather than just defaulting new ones to Vapor Mode has been a slower, ongoing process, and we've been deliberate about not forcing it. A component that works fine under the older renderer and isn't on a performance-sensitive screen gets left alone until someone touches it for an unrelated reason, at which point converting it becomes a small addition to that other work rather than a dedicated migration task competing for its own sprint slot. That approach means our codebase currently has a genuine mix of both rendering approaches coexisting, which Vue supports cleanly, and we've felt no urgency to force a full conversion just for the sake of consistency.

The exception to that patience has been anything on our busiest internal dashboards, where we did prioritize deliberate conversion of existing components specifically because the performance benefit was large enough to justify pulling engineering time away from other work. Those targeted conversions were where we first proved out Vapor Mode's benefit concretely enough to justify making it the default everywhere else, and we'd recommend that sequencing to any team considering a similar migration: prove the benefit on your most demanding real screen before flipping the default for everything else.

← Back to the journal

Have a project in mind?
Let’s talk.

Tell us where you are and where you want to go. We'll map the fastest route between the two.

Currently accepting new clients