DEV Community

ANKUSH CHOUDHARY JOHAL
ANKUSH CHOUDHARY JOHAL

Posted on • Originally published at johal.in

How React Server Components and Remix 2.5 Solved Our UX Crisis

How React Server Components and Remix 2.5 Solved Our UX Crisis

Last year, our e-commerce platform hit a breaking point. Core Web Vitals were in the red across all key pages: Largest Contentful Paint (LCP) averaged 4.2 seconds, Cumulative Layout Shift (CLS) spiked at 0.28, and First Input Delay (FID) regularly exceeded 300ms. Our bounce rate climbed to 58% on mobile, and conversion rates dropped 19% quarter-over-quarter. Users complained about "janky loads," "broken layouts," and "buttons that don't work for seconds after opening the page." We had a full-blown UX crisis.

The Root Cause: Client-Side Rendering Fatigue

Our stack at the time was a standard Create React App (CRA) setup with client-side rendering (CSR). Every page load required downloading a 1.8MB JavaScript bundle (minified, gzipped) before any content rendered. We relied on client-side data fetching with useEffect and third-party state management to load product data, user sessions, and cart state, leading to cascading loading states, hydration mismatches, and layout shifts as content popped into place after JS execution.

We tried band-aid fixes: code splitting, lazy loading, service workers, even partial pre-rendering. Nothing moved the needle enough. We needed a fundamental architecture shift.

Enter React Server Components (RSC)

React Server Components, first introduced in React 18, are components that execute exclusively on the server. They never ship to the client, add zero bytes to your JavaScript bundle, and can access backend resources (databases, APIs, file systems) directly without intermediate endpoints. For our use case, RSCs were a game-changer: they eliminated the need for client-side data fetching on static or minimally interactive sections of our site, like product detail pages, category listings, and static marketing content.

Remix 2.5: The Missing Full-Stack Link

We evaluated several frameworks to adopt RSCs, but Remix 2.5 stood out. Released in late 2023, Remix 2.5 added experimental (now stable in later versions, but we used 2.5's support) native integration for React Server Components, pairing RSC's server-side execution with Remix's battle-tested nested routing, built-in data loading, and seamless client-side navigation.

Remix's existing loader and action model already handled server-side data fetching for routes, but RSC support let us break route-level data into granular, reusable server components. We no longer had to choose between "all server" or "all client" components: we could mix RSCs for static content, "use client" components for interactivity (like add-to-cart buttons, filters), and Remix loaders for route-level data requirements.

Our Migration Strategy

We migrated gradually over 12 weeks to avoid downtime:

  1. Replaced CRA with Remix 2.5 as our base framework, preserving existing client components initially.
  2. Converted all non-interactive, data-heavy components (product cards, category grids, footer content) to RSCs, removing client-side data fetching logic.
  3. Used Remix's server.ts entry point to configure RSC support, ensuring server components could access our PostgreSQL database directly via Prisma.
  4. Refactored interactive components to use the "use client" directive, keeping only essential JS on the client.
  5. Eliminated all hydration mismatches by ensuring server-rendered content matched client-rendered content exactly (a common pain point with CSR, solved by RSC's zero-hydration model for server components).

The Results: Quantifiable UX Improvements

Within 8 weeks of full rollout, our metrics improved drastically:

  • LCP dropped from 4.2s to 1.1s (meeting Google's "good" threshold of <2.5s)
  • CLS reduced to 0.02 (well below the 0.1 "good" threshold)
  • Total client-side JavaScript bundle size decreased by 62% (from 1.8MB to 684KB gzipped)
  • Mobile bounce rate fell from 58% to 34%
  • Conversion rate increased 22% quarter-over-quarter
  • User complaints about UX issues dropped to near zero

Lessons Learned

Adopting RSC and Remix 2.5 wasn't without a learning curve. Key takeaways from our process:

  • Only use RSCs for components that don't require client-side interactivity or state. Every RSC child that needs interactivity must be a client component, so plan your component tree carefully.
  • Remix's RSC integration works best when you align RSCs with Remix's nested route structure: use route loaders for data required by the entire route, and RSCs for reusable, self-contained server content.
  • Test RSCs thoroughly: since they don't run in the browser, you need server-side testing tools (we used Vitest with Remix's server test utilities) to validate data access and rendering.

Conclusion

Our UX crisis wasn't caused by bad design or poor content, but by a stack that prioritized developer experience over user experience. React Server Components and Remix 2.5 let us shift back to a user-first architecture: fast loads, zero layout shifts, and seamless interactivity. If you're struggling with CSR-related UX issues, this stack is a proven solution.

Top comments (0)