FrameworksGENERALFRAMEWORK-SPECIFICSPEC-EVOLVING

Choosing a Framework

There is no winner. There are constraints — team, existing code, hiring, rendering strategy, bundle budget, support horizon — and the framework that fits the most of yours.

The intent, the obvious build, and why it breaks

Every lesson starts where the work starts: someone wanted an outcome, and the first implementation that comes to mind has a problem.

The question

Given what my team, my product and my users actually need, how do I choose, and what am I signing up for?

The user intent

A team is starting something they intend to run for five years. They want to make one decision now that they will not have to unmake in eighteen months.

The obvious build

Compare the benchmarks and the bundle sizes, pick the framework that wins, and get on with it. The technical answer is the answer.

Why it breaks

The benchmark measures keyed list reconciliation on a fast machine. Real applications are dominated by data fetching, bundle size, third-party scripts and layout — none of which the benchmark touches (Measure Before Optimising).

How it breaks in a real browser
  • The benchmark measures keyed list reconciliation on a fast machine. Real applications are dominated by data fetching, bundle size, third-party scripts and layout — none of which the benchmark touches (Measure Before Optimising).
  • Bundle size comparisons are usually taken at the size no real application has. The runtime floor and the per-component cost trade against each other, and which one dominates depends on how many components you end up with (Bundle Analysis).
  • The decision is mostly not technical. Who is available to hire, what your team already knows, what your existing code is written in, and who will maintain this in three years all outweigh a millisecond of update cost.
  • It is also not a single decision. Rendering strategy, router, data layer, component library and build tooling are separable choices, and some of them matter more to your users than the framework does (Choosing a Rendering Strategy).
  • And it is reversible only in theory. A framework choice propagates into every component, every test, every hire and every library dependency; changing it later is a rewrite priced as a refactor.
IntentEventStateUI LogicDOM WorkNetworkLayout / PaintPixelsFeedback

What is actually happening

In the browser, not in the framework.

  • The criteria that actually predict regret are: what the team already ships, what you can hire for, what your existing code is, what rendering strategy you need, what your bundle budget is, and how long you need this to be supported.
  • Team knowledge compounds. A framework the team knows produces working software immediately and produces good decisions six months in. A framework they are learning costs you both, at once, on your first deadline.
  • Ecosystem is a risk position. A large ecosystem means an existing answer to most problems and a large surface of unmaintained packages. A small one means fewer answers and more first-party consistency (Third-Party Scripts and the Supply Chain).
  • Server rendering is the axis most likely to be decided for you. If the product depends on content being visible to crawlers, to link previews, or to a user on a slow connection before JavaScript arrives, the meta-framework matters more than the view layer (Server-Side Rendering).
  • Bundle budget interacts with everything. The framework is one term; the router, the data layer, the component library, the date library and the analytics script are the others, and they are frequently larger (The Real Cost of JavaScript).
  • Support horizon is a constraint, not a preference. How long releases are supported, how upgrades have historically gone, and how much of the ecosystem follows are all knowable before you commit (Long-Lived Clients and Version Skew).

What this makes the browser do

And which of it is avoidable.

  • Whatever you choose, the browser does the same job: parse and compile the JavaScript, run it, mutate the DOM, then style, layout, paint and composite (The Rendering Pipeline).
  • The framework decides how much JavaScript runs per update. The application decides how much JavaScript exists, and that is usually the larger number (The Real Cost of JavaScript).
  • Hydration cost is a function of the rendering strategy and the amount of interactive surface, and it is more likely to dominate your loading profile than the update model is (Hydration).
  • Third-party scripts do not care which framework you chose, and on many real sites they are the biggest main-thread contributor by a wide margin (Third-Party Scripts and the Supply Chain).

The decision, with the costs attached

Every option below is a defensible choice made by serious teams shipping serious products. The point of the list is not to rank them; it is that each when comes with a cost you are agreeing to, and the choice is which cost you would rather carry.

Note the last two options. "The one your team already ships" is frequently the correct answer and is almost never argued for, because it is not interesting. "No framework" is a real option that is under-considered for small, long-lived, mostly-static surfaces, and over-considered for applications with complex state.

Which framework, for this product, with this team?

What constraint dominates: hiring, consistency, bundle, update cost, or the code you already have?

React

when You need the widest hiring pool, the largest library ecosystem, and an existing answer to almost any problem; or you already have React code.

cost Assembling your own stack from an ecosystem with real churn, a re-render model that needs escape hatches at scale, and a large surface of packages that will be abandoned.

Vue

when You want strong first-party defaults for routing, tooling and state without an entirely integrated framework, and templates your designers can read.

cost A smaller hiring pool than React in most markets, and two systems — compiler and tracking runtime — to understand when reactivity behaves unexpectedly.

Svelte

when Bundle size and per-update work matter, the application is small to medium, and you want less framework at runtime.

cost Semantics that live in a build step, a smaller ecosystem and hiring pool, and per-component code that grows with component count.

Solid

when The application is update-heavy — a dashboard, an editor, a canvas — and minimal per-update work is worth a stricter reactivity contract.

cost The smallest ecosystem of the five, fewer engineers who have used it, and a model that requires unlearning re-render habits.

Angular

when A large or multi-team organisation, a long maintenance horizon, and consistency across many codebases is worth more than flexibility.

cost The largest runtime floor, the most to learn before the first useful commit, and an in-progress transition between two change-detection models.

The one your team already ships

when You have working code, working knowledge, and a deadline. This is the correct answer far more often than it is chosen.

cost You inherit its constraints, including the ones that prompted the question — so write down what specifically is not working before you overrule this.

No framework

when A mostly-static site, a widget embedded in someone else's page, or something that must still work unchanged in ten years.

cost You reimplement routing, state, accessible components and rendering as you need them — including the accessible-component part, which is the expensive one (Accessible Component Patterns).

Constraints, and what each one should actually move

A framework argument goes badly when the participants are weighing different constraints without saying so. Making the weighting explicit converts an argument about taste into a shared decision, and usually shortens it considerably.

Read the last column as the honest one. Several of these constraints should not move your framework choice at all — they should move a different decision, and mistaking which is how teams end up choosing a view layer to solve a delivery problem.

ConstraintWhat to askWhat it should move
Team knowledgeWhat has this team shipped and maintained before?The framework choice, more than anything else on this list
Existing codeWhat is already written, and who maintains it?The framework choice, or the decision not to make one
HiringWho can we hire where we actually hire, in two years?The framework choice, weighted by how much you plan to grow
Server renderingDo users need content before JavaScript runs?The meta-framework and rendering strategy first, the view layer second (Choosing a Rendering Strategy)
Bundle budgetWhat is the total budget, including everything that is not the framework?A CI budget check. Framework choice is one term of several (Bundle Analysis)
Update-heavy UIAre there high-frequency updates over large collections?The update model — and virtualisation first, which usually matters more (List Virtualization)
Accessibility requirementsWhat does the component library actually do with keyboard and focus?The component library, and your testing practice. Not the framework (Accessibility Testing)
Support horizonHow long are releases supported, and how have upgrades gone?The framework choice for anything long-lived (Long-Lived Clients and Version Skew)
Ecosystem needsDoes the one hard component we need already exist and work?The framework choice, if that component is genuinely central

How this decision actually goes wrong

The failures below are not hypothetical framing devices; they are the recurring shapes of a decision made on the wrong evidence. Each has the same structure: a real signal was measured, and it was not the signal that predicted the outcome.

Choosing on the wrong evidence
TriggerSymptomCauseResponse
Chosen on benchmark resultsThe app is still slow after the rewriteThe bottleneck was data fetching, images and third-party scriptsProfile the existing product first. The framework is rarely the top entry (Measure Before Optimising).
Chosen on a hello-world bundle sizeThe shipped bundle is dominated by everything elseRuntime floor was compared instead of the real applicationPrototype the hardest screen and measure the whole bundle (Bundle Analysis).
Chosen for team enthusiasmThe first deadline slips on unfamiliar toolingLearning cost landed on the critical pathWeight existing knowledge explicitly, or buy the learning time before the deadline exists.
Chosen without the rendering strategyContent is invisible to crawlers and slow on first loadThe view layer was chosen before the delivery modelDecide the rendering strategy alongside the framework (Choosing a Rendering Strategy).
Chosen, then migrated mid-projectTwo partial applications, one team, no deliveryThe cost of a framework change was priced as a refactorFinish, then migrate deliberately at a boundary — and price it as the rewrite it is (Micro Frontends).
Chosen well, with no bundle or a11y budgetA fast framework inside a slow, inaccessible productThe framework was the only decision anyone reviewedPut budgets and accessibility checks in CI, where they outlive the decision (Accessibility Testing).

How to build it

Most important first.

  • Write down your constraints before you look at any framework: team, hiring market, existing code, rendering needs, bundle budget, accessibility requirements, support horizon. The list is the decision; the framework is the conclusion.
  • Weight team and existing code heavily. They are the constraints most likely to decide whether the project ships, and the ones most often left out of the comparison.
  • Decide the rendering strategy alongside the framework, because it determines which meta-framework you are really choosing and it affects users more directly (Choosing a Rendering Strategy).
  • Prototype the hardest screen, not the easiest. A todo list tells you nothing; the screen with a virtualised table, a complex form and live updates tells you everything (List Virtualization).
  • Check the accessibility story concretely: what the component library actually does with keyboard and focus, what the router does on navigation, and what the testing tools can assert (Accessibility Testing).
  • Record the decision and its reasons somewhere durable. In two years the constraints will have changed, and you will want to know which ones you were optimising for.

Keyboard, focus, semantics, announcement

A required field on every lesson in this domain, not a section added when there is room.

  • No framework here makes a UI accessible, and every one makes it possible to build an inaccessible one without a single warning (Semantics Before ARIA).
  • What differs is the surrounding ecosystem: whether the component library you will actually use has real keyboard support and focus management, and whether the router gives you a place to announce navigation (Accessible Component Patterns).
  • Client-side routing is an accessibility decision in every framework. A view swap with no announcement and no focus move is a silent navigation for a screen-reader user (Client-Side Routing).
  • Frameworks that replace DOM nodes more aggressively lose focus more often. It is a real difference and it is a smaller one than the difference between a team that tests with a keyboard and one that does not (Focus Management).
  • Ask what the testing story is for accessibility before you commit, because an automated check finds a minority of issues in every framework (Accessibility Testing).

What can go wrong

Failure modes
  • Choosing for a benchmark and discovering the bottleneck was your data layer, your images and a tag manager.
  • Choosing the framework the team is most excited about and paying for it in the ramp-up on the first deadline.
  • Choosing for a hiring market that does not exist where you are actually hiring.
  • Choosing a view layer and then discovering that server rendering, routing and data loading were the real decisions (Choosing a Rendering Strategy).
  • Migrating mid-project, which delivers two half-finished applications and a shared vocabulary problem (Micro Frontends is often proposed here and is a bigger commitment than it looks).
  • Choosing correctly and then losing the benefit to a component library with no keyboard support, a chart library that ships a megabyte, and no bundle budget in CI.
Security
  • All five escape interpolated text and all five provide a raw-HTML door. The security difference between them is close to zero; the difference between codebases that audit those calls and codebases that do not is large (Cross-Site Scripting).
  • The dependency tree is the real exposure, and it grows with ecosystem size and with how much you assemble yourself (Software Supply Chain Security in Security).
  • A framework with a first-party stack has a smaller third-party surface by construction, which is a genuine security property and also a constraint on what you can use.
  • Server-rendering anything means your component code runs on a server, and every framework here has the same module-scope hazard when it does (Server-Side Rendering).
Misreads
  • "There is a best framework." There is a best fit for a set of constraints, and constraints differ per team, per product and per year. Anyone who answers without asking about your team is answering a different question.
  • "Framework choice is the most important frontend decision." Rendering strategy, data layer, bundle budget and third-party scripts each move user-visible numbers more, in most products (Choosing a Rendering Strategy).
  • "Popular means correct." Popularity is a real advantage in hiring and libraries and is not an argument about the technology.
  • "We can migrate later." A framework choice reaches every component, every test and every hire. Later migration is a rewrite, and it competes with the roadmap for years.
  • "Small bundle means fast." Bundle size is one term in loading, and loading is one of three concerns users actually feel (Measure Before Optimising).

Measuring it, and what changes in the field

How you would see this
  • Prototype your hardest screen in the two finalists and measure both on a mid-range device — the only benchmark that is about your application (Measure Before Optimising).
  • Measure the whole bundle for that prototype, including router, data layer and component library, not the framework in isolation (Bundle Analysis).
  • Measure the team: how long to a working feature, how many questions had no findable answer, how much of the code review was about the framework rather than the product.
  • Check field data from products already built with each candidate, if you can get it. Real loading and interaction data beats any comparison you can construct (Real User Monitoring).
Slow device, slow network, large data, old tab
  • For a small team with a deadline, existing knowledge dominates everything else on this list.
  • For a large organisation with many teams, consistency and a supported upgrade path dominate, and an opinionated stack becomes an advantage rather than a constraint.
  • For a content-heavy product, the rendering strategy and delivery decide what users feel, and the update model barely registers (Loading: Why Content Arrives Late).
  • For a highly interactive application — an editor, a dashboard, a canvas tool — the update model genuinely matters, and so does the ecosystem for the specific hard components you need.
  • For a long-lived internal application, the support horizon and upgrade cost outrank everything a user will notice.
What this costs
  • Choosing the popular option buys hiring, libraries and answers, and costs you the churn of a large ecosystem and a large surface of packages that will be abandoned.
  • Choosing the integrated option buys consistency and a smaller decision surface, and costs flexibility where the first-party answer does not fit.
  • Choosing the smallest, newest option buys a model you may genuinely prefer and costs you libraries, examples and the availability of people who have already made your mistakes.
  • Choosing nothing — the platform plus a small amount of code — buys minimal dependency and longevity and costs you every convenience you will otherwise reimplement, including the hard ones (Accessible Component Patterns).

Where this applies

Frontend advice ages badly and fragments across engines. These labels say what each claim is specific to, and where a different browser, device or framework would differ.

  • GENERALThe criteria — team, existing code, hiring, rendering needs, bundle budget, ecosystem, support horizon — apply to any framework choice, including choosing none. What varies is the weighting, and the weighting is a property of your organisation rather than of the frameworks.
  • FRAMEWORK-SPECIFICThe option costs listed below are about the five frameworks in this module as they currently stand: React's ecosystem size and churn, Vue's and Svelte's strong first-party defaults, Solid's smaller ecosystem, Angular's integrated stack and larger runtime floor. Each of those has moved within recent memory and should be re-checked rather than quoted.
  • SPEC-EVOLVINGFramework capabilities converge quickly: signals, compilers, server rendering models and streaming have all crossed between these projects in recent releases. A comparison written today is a snapshot, and the criteria outlive the conclusions.

Where the depth lives

This domain teaches the browser-side mechanism and hands the rest off.

Domains that do not exist yet
  • Software Design — a framework choice is a dependency-direction decision at the largest scale you make one, and the parts of your application that do not depend on it are the parts that survive the next one.
  • Testing & Reliability Engineering — what each candidate lets you test, and how fast, is a constraint that belongs in the comparison and is almost never in it.