Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversHalloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PC×
Skip to content
World desk6 min

How I Made My React Portfolio 2× Faster: Lighthouse 30 to 80 With a Prerendered Vite App

Shreyash Tripathi’s portfolio gained route-specific HTML at build time, alongside several other optimizations. Here’s how the setup worked and what the Lighthouse results do—and don’t—show.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Shreyash Tripathi reported that his portfolio’s mobile Lighthouse 12 Performance score rose from 30 to 80 after he prerendered its known routes and made several other performance changes. His build generated route-specific HTML, then the browser hydrated that content. The result is a useful Vite and React case study—not a guarantee that prerendering alone will produce the same score on another site.

What changed in the portfolio

Before the change, the portfolio relied on client-side rendering for most of its visible page content. The browser had to download and run JavaScript before it could render much of the interface. Tripathi changed the build so it produced HTML for each known route in advance. On a visit, the browser could receive meaningful page markup immediately, then run the client app to make it interactive.

As an Amazon Associate I earn from qualifying purchases.

The implementation follows a familiar split: a shared React app, a server entry that renders a route, and a client entry that hydrates the returned HTML. Vite’s SSR guide describes this general structure, while noting that its lower-level SSR API is primarily aimed at library and framework authors; it is not the only route for application developers. Vite’s SSR guide

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How the build generated route HTML

Render each known route during the build

The project’s build command first ran the normal Vite build, then an SSR build for src/entry-server.tsx, and finally a Node prerender script. The server entry used React’s renderToString together with React Router’s StaticRouter to render the app for a specific URL.

The script iterated through the portfolio’s known routes, rendered each route, and inserted its markup into the HTML template in place of the root placeholder. The output was therefore a set of HTML pages prepared ahead of deployment rather than one mostly empty app shell.

Hydrate the existing markup in the browser

The client entry checked whether the root element already contained children. If it did, it called hydrateRoot so React could attach behavior to the generated HTML. If no markup was present, it fell back to createRoot. Hydration depends on the server-rendered and client-rendered trees matching; inconsistent routes or providers can cause problems.

React’s documentation distinguishes static generation from rendering on each request and notes that adding a build-time static-generation setup can increase setup and maintenance work compared with a simple single-page app. React’s app-from-scratch guidance

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Prerendering was one part of a broader optimization

The before-and-after comparison covered multiple changes, so it cannot identify how much improvement came from prerendering alone. Alongside generating route HTML, Tripathi reports that he:

  • Deferred interactive effects so they did not block the initial render.
  • Delayed a chart until it was near the viewport.
  • Compressed the profile image.
  • Changed animation techniques and reduced costly blur effects.
  • Adjusted font loading.
  • Removed an autoplay boot screen. Tripathi’s description in the case study: “It was fun. It was also my LCP.”

That mix matters: putting content in the initial HTML can help it appear sooner, but heavy scripts, images, fonts, and effects can still affect loading and responsiveness.

What the author measured

Tripathi reported the following before-and-after results from Lighthouse 12 in mobile emulation. These are the author’s lab measurements, not field data, an independent replication, or a controlled test of prerendering in isolation. Read the case study

Measure Before After What it describes
Performance score 30 80 Lighthouse’s composite mobile lab score
Largest Contentful Paint (LCP) 8.1 s 3.4 s Time until the largest visible content element is rendered
Total Blocking Time (TBT) 3,390 ms 240 ms Main-thread blocking time during the Lighthouse lab test
Cumulative Layout Shift (CLS) 0.014 0 Measured visual layout instability
Words visible without JavaScript 134 1,007 Visible text in the page before client-side JavaScript runs

The figures demonstrate the outcome on this portfolio under the author’s test conditions. They do not establish what another app will score, or how much any single change contributed.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose a rendering approach based on the app

Prerendering, request-time server-side rendering, and client-side rendering solve different delivery problems. The useful choice depends on whether routes and their content are known in advance, whether they vary per visitor, and how much runtime and maintenance complexity the project can accept. web.dev’s rendering overview

Approach When HTML is generated Good fit Trade-offs
Build-time prerendering / static generation During the build, ahead of a request A finite set of routes whose content is known or can be fetched at build time, such as a portfolio Can serve ready-to-render HTML from static infrastructure, but every required route must be generated and updated when its content changes. Very large or unpredictable URL sets can be difficult to enumerate.
Request-time SSR On the server for each request, or as needed by the server’s caching strategy Pages that depend on request-specific data or personalization Can produce a response for dynamic requests, but server rendering adds work at request time and requires a runtime server setup.
Client-side rendering Primarily in the browser after JavaScript loads Apps where the initial page need not expose substantial content before the client app runs Simple deployments can be attractive, but users may wait for scripts before meaningful content appears. Moving to prerendering does not remove the need for client JavaScript if the page requires interactive behavior.

Static HTML can be deployed to a CDN, and static rendering can support fast first content paint and time to first byte. That does not mean a prerendered page is automatically interactive: hydration and other client scripts still have to execute. As web.dev explains, hydration can delay interaction while JavaScript runs, and prerendering that improves an SPA’s initial paint is not the same as delivering a page that needs little client-side JavaScript.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Implementation details that can trip up hydration

Keep the rendered app tree consistent

The route and shared providers used by the server render need to correspond to the client tree that hydrates it. If they produce different markup, React may not be able to hydrate the HTML cleanly. In this case study, the author found that the shared providers and route tree had to be represented consistently.

Be careful with Suspense and lazy components

Tripathi reports that a lazy component inside Suspense caused the renderToString path to emit a fallback to client rendering. If a route’s server output depends on a lazy boundary, test the generated HTML and hydration behavior for that route rather than assuming the server render contains the final component.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

React documents separate static rendering APIs, which are relevant when generating static HTML rather than rendering a response for a live request. React’s static React DOM APIs

How to evaluate the result on your own app

  1. List the URLs you can know at build time. If page content depends on each visitor or changes per request, decide how that data will be delivered before choosing build-time output.
  2. Generate and inspect HTML for representative routes. Confirm that the initial document contains the content you expect before JavaScript runs, including route-specific content rather than just a shared shell.
  3. Test hydration and interactive behavior. Check routes with providers, lazy components, and Suspense boundaries, and look for mismatches or client-rendered fallbacks.
  4. Measure with repeatable conditions. Compare the same routes and mobile test settings before and after changes. Treat a Lighthouse result as a lab signal, not a promise about every visitor’s experience.
  5. Profile React work when needed. React’s <Profiler> can measure rendering of a tree, but profiling adds overhead and is disabled in production by default. It is a diagnostic tool, not proof that prerendering will improve a particular site. React Profiler reference

When this approach is a sensible fit

A portfolio with a manageable set of mostly stable URLs is a natural candidate for build-time HTML generation: the pages can be prepared ahead of time, and the browser can receive readable content before the React app hydrates. An app with request-specific pages may instead need request-time rendering or another way to supply that dynamic content. Whichever route you take, treat rendering strategy as one part of performance work—not a substitute for addressing large assets, main-thread tasks, layout shifts, and client-side code.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.