React or a site without a framework: when React pays off

When a site needs React and when a framework only adds weight: a measured bundle size, a comparison of three approaches, what the browser does by itself, islands, the same tasks written both ways and common mistakes.

Stack and technologies Updated

In short

React is worth it when the interface works like an application: many states on one screen, live data, complex forms and editors — personal accounts, dashboards, SaaS, Mini Apps. For sites whose job is to show content and lead to a request — corporate sites, landing pages, catalogues, blogs — a framework mostly adds weight: a minimal React app is about 66 KB of compressed JavaScript before your own code, while the browser today handles modal windows, popovers, form validation and page transitions by itself. The best of both is common: pages are server HTML, and React lives only in the blocks that really need it.

In short: when React, and when without it

Ask one question: does the screen live after loading? If the person mostly reads, compares and fills in a form — the page should come ready from the server, and a little JavaScript adds the rest. If the person works inside the screen for hours — filters, drags, edits, gets live updates — the amount of state grows, and React keeps it under control.

The mistake is choosing by habit: a landing page on React because “everyone does it”, or a complex dashboard on scattered scripts because “a framework is heavy”. Both cost money — the first in speed and search, the second in bugs and development time.

  • The screen is read — server HTML
  • The screen is worked in — React
  • Often — both on one site

How much React weighs: a measurement

The same button with a counter, built by Vite 8 in production mode. React 19.3; sizes of the JavaScript file.

React, minified
214 KB
React, gzip over the network
66 KB — before any code of your own
Plain JavaScript, minified
0.8 KB
Plain JavaScript, gzip
0.5 KB
What it means
On a fast connection the difference is small; on a weak phone the browser also has to parse and run that code before the page responds

React, React with server rendering, or no framework

Three common approaches side by side. React with server rendering means frameworks like Next.js.

CriterionReact in the browserReact + server (Next.js)Server HTML, no framework
First screen after JavaScript loads and runs comes ready, then comes alive comes ready
Content for search engines only after JavaScript in the HTML in the HTML
JavaScript weight tens of KB and up tens of KB and up only what the page needs
Complex interactive screens strong strong harder as states multiply
Hosting any static hosting a Node.js server or a platform any, including shared
Dependencies to update many many, plus the framework few
The project in five years needs regular upgrades follows the framework’s changes works as written
Developers on the market very many many any web developer
Best for personal accounts, SaaS, Mini Apps large products with public pages sites, landing pages, catalogues, blogs

What the browser can do without a framework today

Much of what used to need a library is now built into HTML and CSS — with accessibility included.

  1. Modal windows

    <dialog> gives a backdrop, closing on Esc and keeps the focus inside.

  2. Popovers and menus

    The popover attribute opens and closes them without a line of JavaScript.

  3. Accordions

    <details> and <summary> — and the content stays visible to search engines.

  4. Form validation

    required, type="email", pattern and clear messages from the browser itself.

  5. Page transitions

    View Transitions animate the move between pages like in an application.

  6. Responsive components

    Container queries and :has() adapt a block to its place without scripts.

Which approach for which project

Twelve typical projects with a recommendation and the reason.

ProjectTakeWhy
Landing page no framework speed on mobile decides the conversion
Corporate site no framework content, search and a form
Blog or media no framework pages are read, not worked in
Catalogue with filters no framework or islands pages for search, filters as a small script
Online shop islands server pages, React in the cart and checkout if they are complex
Calculator on a site an island one interactive block on an ordinary page
Personal account React many states and live data
Dashboard or admin panel React tables, filters and editing in one screen
SaaS product React the interface is the product
Telegram Mini App React an application inside the messenger
Editor or builder React drag and drop, undo, live preview
Large product with public pages Next.js React everywhere, but pages come ready for search

The middle ground: islands

The page is rendered on the server as ordinary HTML — fast, visible to search engines, working without JavaScript. Where a block really needs to live — a calculator, a configurator, a cart — React is mounted only into that block. The rest of the page does not pay for it.

Lighter tools work the same way: Preact gives React’s approach in a few kilobytes, htmx and Alpine.js add behaviour with attributes, and Astro builds whole sites out of islands. The choice depends on the team and on how much the interactive part will grow.

  • The page is HTML from the server
  • React only where the block lives
  • The rest of the page does not pay

The same tasks with React and without: 5 examples

A modal window and a list search written both ways, plus an island. React examples are checked by TypeScript 7 in strict mode, HTML examples — in Chromium.

Modal window: React

State in the component; closing on Esc and keeping focus inside have to be written separately.

Subscribe.tsx
import { useState } from 'react';

// React: the window state lives in the component; Esc and focus are up to you
export function Subscribe() {
  const [open, setOpen] = useState(false);
  return (
    <>
      <button onClick={() => setOpen(true)}>Subscribe</button>
      {open && (
        <div role="dialog" aria-modal="true" className="modal">
          <p>Leave your email — we write once a month.</p>
          <button onClick={() => setOpen(false)}>Close</button>
        </div>
      )}
    </>
  );
}

Modal window: no framework

<dialog> does the work: backdrop, Esc and focus come from the browser.

subscribe.html
<!-- no framework: the browser handles Esc, focus and the backdrop itself -->
<button id="open">Subscribe</button>

<dialog id="subscribe">
  <p>Leave your email — we write once a month.</p>
  <form method="dialog"><button>Close</button></form>
</dialog>

<script>
  document.getElementById('open').addEventListener('click', () => {
    document.getElementById('subscribe').showModal();
  });
</script>

List search: React

The list is built in the browser — until JavaScript runs, there is nothing on the page.

Search.tsx
import { useState } from 'react';

const products = ['Oak table', 'Oak chair', 'Pine shelf', 'Walnut desk'];

// React: the list is built by JavaScript in the browser
export function Search() {
  const [query, setQuery] = useState('');
  const found = products.filter((p) => p.toLowerCase().includes(query.toLowerCase()));
  return (
    <>
      <input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Search" />
      <ul>
        {found.map((p) => (
          <li key={p}>{p}</li>
        ))}
      </ul>
    </>
  );
}

List search: no framework

The list comes from the server and is visible at once; the script only hides what does not match.

search.html
<!-- the list comes from the server: search engines see it, JavaScript only hides -->
<input id="q" type="search" placeholder="Search">
<ul id="list">
  <li>Oak table</li>
  <li>Oak chair</li>
  <li>Pine shelf</li>
  <li>Walnut desk</li>
</ul>

<script>
  const items = [...document.querySelectorAll('#list li')];
  document.getElementById('q').addEventListener('input', (e) => {
    const q = e.target.value.toLowerCase();
    for (const li of items) li.hidden = !li.textContent.toLowerCase().includes(q);
  });
</script>

An island: React in one block

The page stays server HTML, and React is mounted only where a calculator needs to live.

calculator.tsx
import { createRoot } from 'react-dom/client';
import { Calculator } from './Calculator';

// the page is plain server HTML; React lives in a single block
const mount = document.getElementById('calculator');
if (mount) {
  createRoot(mount).render(<Calculator rate={Number(mount.dataset.rate)} />);
}

Common mistakes when choosing

  1. A landing page as a single-page app

    The ad visitor waits for JavaScript on a weak phone — and leaves before the first screen.

  2. Content only in the browser

    Search engines read it worse, and most AI crawlers do not run JavaScript at all.

  3. A dashboard on scattered scripts

    Without a model of state, every new feature breaks two old ones.

  4. React for one button

    Tens of kilobytes for what <dialog> or popover does natively.

  5. Choosing by the team’s habit

    The task decides the tool, not the other way round.

  6. Forgetting updates

    A framework project left for two years needs a migration before any new feature.

Questions about React and sites without a framework

Does a website need React?

A site that is read — usually not. An interface people work in — usually yes.

Is a React site worse for SEO?

If the content is built only in the browser — yes. With server rendering (Next.js) the content is in the HTML, and the problem goes away.

How much does React weigh?

A minimal React 19 app built by Vite is about 66 KB in gzip before your own code; the same button in plain JavaScript is half a kilobyte.

Is a site without a framework harder to maintain?

For content sites — the opposite: fewer dependencies, fewer updates, and any web developer can read the code.

Can React be added later?

Yes, as islands: a new interactive block gets React without rewriting the site.

What is Next.js?

A React framework that renders pages on the server so they come ready for people and search engines.

What about Vue or Svelte?

The same logic applies: they are tools for interfaces that live. Svelte compiles to less JavaScript, but the question “does the screen live?” stays.

Will a site without a framework look outdated?

The look does not depend on a framework: animations, transitions and modern layout are done with CSS and the browser itself.

Online form

React or
own code

I choose the approach for the task: React with TypeScript where the interface works like an application, and fast server HTML without a framework everywhere else. Tell me about the project — I answer within one working day.

Or write to [email protected]