Performance & Production

I'll never forget deploying my POS system to production for the first time. It worked perfectly on my laptopβ€”instant renders, smooth scrolling, fast navigation. Then I tested it on a customer's old tablet over 3G. The initial load took 15 seconds. Every cart update caused a 2-second freeze. The product list re-rendered everything when I clicked "Add to Cart". It was unusable.

That's when I learned: performance doesn't just happen. You have to measure, identify bottlenecks, and optimize strategically. I added React.memo to prevent unnecessary renders, useMemo to cache expensive calculations, code splitting to reduce bundle size, and proper loading strategies. The result? Initial load: 2 seconds. Cart updates: instant. The app felt native.

Measuring Performance First

Never optimize blindly. Measure first, then optimize what matters.

React DevTools Profiler

  1. Install React DevTools browser extension

  2. Open DevTools β†’ Profiler tab

  3. Click record, interact with your app, stop recording

  4. See which components rendered and how long they took

In the POS, I discovered:

  • ProductList re-rendered every time cart updated (unnecessary!)

  • Cart total calculation ran on every render (expensive!)

  • Every ProductCard re-rendered when one was clicked

Chrome DevTools Performance Tab

  1. Open Chrome DevTools β†’ Performance

  2. Record while interacting

  3. Look for long tasks (yellow blocks)

  4. Find scripting time, rendering time

Use this to find:

  • Slow network requests

  • Heavy computations

  • Large re-renders

useMemo: Caching Expensive Calculations

Problem: Calculations run on every render, even when inputs haven't changed.

Without useMemo (Slow)

Problem: Even if you just click a button that doesn't change the cart, all these calculations run again.

With useMemo (Fast)

Now: Calculations only run when cart changes, not on every render.

Real Example: Complex Product Filtering

useCallback: Stable Function References

Problem: Functions created in render are new objects every time, causing child re-renders.

Without useCallback (Causes Re-renders)

Problem: Even if ProductCard is memoized, it re-renders because onAdd is a new function every time.

With useCallback (Stable Reference)

Real Example: Event Handlers

React.memo: Preventing Component Re-renders

Problem: Child components re-render even when their props haven't changed.

Without React.memo (Re-renders Always)

Problem: When you add ONE product to cart, ALL ProductCard components re-render.

With React.memo (Re-renders Only When Props Change)

Now: Only re-renders when product or onAdd change. If you add a different product to cart, this card doesn't re-render.

Custom Comparison Function

Real Example: Optimized Product List

Result: Adding one product to cart only re-renders that one card + cart component, not all 100 product cards.

When NOT to Optimize

Don't optimize prematurely! These techniques add complexity.

Don't Use useMemo for Simple Calculations

Don't Memo Every Component

Only Optimize When You See Problems

  1. Measure with Profiler

  2. Identify slow components

  3. Optimize those specific components

  4. Measure again to verify improvement

Golden Rule: Premature optimization is the root of all evil. Profile first, optimize what matters.

Code Splitting with lazy() and Suspense

Problem: Initial JavaScript bundle is huge. Users download code for admin panel even if they never go there.

Without Code Splitting (Large Bundle)

With Code Splitting (Small Initial Bundle)

Now:

  • Initial load: ProductsPage + shared code

  • User visits /cart: Downloads CartPage chunk

  • User visits /admin: Downloads AdminPage chunk

Bundle sizes in my POS:

  • Before code splitting: 450 KB initial

  • After: 180 KB initial, 50 KB per route

Better Loading UI

Production Build Optimizations

Environment Variables

Remove Console Logs in Production

Error Boundaries

Catch runtime errors gracefully:

Deployment

Building for Production

Creates optimized build in build/ folder:

  • Minified JavaScript

  • Optimized CSS

  • Asset optimization

  • Source maps (for debugging)

Deploy to Vercel

  1. Install Vercel CLI:

  1. Deploy:

  1. Follow prompts, done!

Vercel automatically:

  • Detects React app

  • Runs npm run build

  • Deploys to CDN

  • Provides HTTPS

  • Gives you a URL

Deploy to Netlify

  1. Build your app:

  1. Drag build/ folder to Netlify

Or use Netlify CLI:

Deploy to Custom Server (Nginx)

Complete Production Checklist

Before deploying to production, verify:

Performance

Functionality

Security

User Experience

Monitoring

Real POS Performance Results

Here's what I achieved in the production POS system:

Before Optimization:

  • Initial bundle: 450 KB

  • Products page load: 3.2s

  • Cart update: 800ms (visible lag)

  • Lighthouse score: 62

After Optimization:

  • Initial bundle: 180 KB (60% reduction)

  • Products page load: 1.1s (66% faster)

  • Cart update: 50ms (94% faster)

  • Lighthouse score: 94

Optimizations Applied:

  1. Code splitting (saved 270 KB initial)

  2. React.memo on ProductCard (eliminated 100+ re-renders)

  3. useMemo for cart calculations

  4. useCallback for event handlers

  5. Image optimization (WebP, lazy loading)

  6. Debounced search input

Key Learnings

  1. Measure before optimizing - use React Profiler

  2. useMemo caches expensive calculations

  3. useCallback provides stable function references

  4. React.memo prevents unnecessary re-renders

  5. Don't optimize prematurely - profile first

  6. Code splitting reduces initial bundle size

  7. lazy() + Suspense for route-based splitting

  8. Error boundaries catch runtime errors

  9. Build and test production builds locally

  10. Monitor performance in production

Final POS System Architecture

Here's the complete, production-ready structure:

Congratulations!

You've built a production-ready React application from scratch. You understand:

  • Components and props

  • State and effects

  • Component communication

  • Context API

  • Custom hooks

  • Routing

  • Performance optimization

  • Production deployment

The POS system we built together demonstrates real-world patterns you'll use in every React app. You're ready to build production applications.

Next Steps

Keep learning:

  • State management: Redux, Zustand, Jotai

  • Server state: React Query, SWR

  • Testing: Jest, React Testing Library, Playwright

  • Advanced patterns: Render props, compound components, HOCs

  • TypeScript: Advanced types, generics

  • Next.js: Server-side rendering, static generation

  • React Native: Build mobile apps with React

Build projects, read code, and never stop learning. Happy coding! πŸš€

Last updated