Frameworks don't make fast sites — discipline does
December 2, 2025
Framework choice matters less than render strategy, bundle discipline, and shipping the smallest useful page. A practical view across React, Next.js, and Svelte.
The framework question is the wrong first question
React, Next.js, and SvelteKit can all produce fast, maintainable applications. They can also all produce slow, unmaintainable ones. The framework doesn't determine the outcome — the decisions made inside it do.
The better questions: Does this framework support the rendering strategy the feature needs? Can the team debug it quickly? Is the ecosystem stable for the dependencies you rely on?
On the rendering question specifically: content pages that don't need interactivity should be statically generated or server-rendered. Shipping a React SPA for a blog or marketing page means your users pay the hydration cost for no user-experience benefit.
Where JavaScript actually costs you
The core performance problem in modern frontend is JavaScript that runs on the main thread at the wrong time. This takes several forms:
Bundle size at initial load — a large bundle delays time-to-interactive even if most of it isn't needed for the first page. Code-split at route boundaries, lazy-load heavy components, and audit what's actually being imported.
Hydration on content pages — server-rendering HTML then shipping a full React tree to hydrate it on the client doubles the work for content that doesn't change. React Server Components and Svelte's partial hydration approach this differently, but both are solving the same problem.
Third-party scripts — analytics, chat widgets, and A/B testing scripts frequently cause more long tasks than the first-party application code. Load them with async or defer, and measure their impact in isolation before adding them.
The fast path for a content-heavy page:
// Next.js: static page with a dynamic section handled client-side
export async function generateStaticParams() {
return posts.map((post) => ({ slug: post.slug }))
}
export default async function PostPage({ params }: { params: { slug: string } }) {
const post = await getPost(params.slug)
return (
<article>
<h1>{post.title}</h1>
<MDXContent source={post.content} />
<Comments postId={post.id} /> {/* client component, loads after content */}
</article>
)
}
The comment section can be a client component that loads lazily — it doesn't block the content from being readable.
Images: the easiest win
Unoptimized images are the most common performance regression on content sites. Next.js's Image component does format conversion, resizing, and lazy loading automatically:
import Image from "next/image"
export function Cover({ src, alt }: { src: string; alt: string }) {
return <Image src={src} alt={alt} width={1200} height={630} priority />
}
priority on above-the-fold images prevents them from being lazy-loaded when they're the largest contentful paint element. Getting this wrong is a common reason for a poor LCP score despite "using the Image component."
Measuring before shipping
Web Vitals — LCP, INP, CLS — are the metrics that correspond to what users actually feel. Run them in CI against a realistic environment, not localhost:
@next/bundle-analyzersurfaces bundle composition- Lighthouse CI in your pipeline prevents regressions from landing unnoticed
- Real User Monitoring (Vercel Analytics, Datadog RUM) shows the production distribution, not the median
Svelte's tradeoff
Svelte compiles components to vanilla JavaScript with no runtime. The output is smaller and faster to parse than the equivalent React bundle. For sites where performance is paramount and the React ecosystem isn't already a dependency, this is a real advantage.
The cost is ecosystem depth. React's component library ecosystem is substantially larger, and some complex UI patterns (virtualized lists, rich text editors) have better-maintained options in React land. For greenfield projects, SvelteKit deserves evaluation. For teams already deep in React, the switching cost needs a clear performance or DX justification.
References
Hi, I'm Martin Duchev. You can find more about my projects on my GitHub.