DEV Community

vanced youtube
vanced youtube

Posted on

Why We Killed CRA: Building a High-Performance Marketplace with React 19 + Vite + Django

Let me be real: if you're still using create-react-app for production apps in 2024, you're fighting your own tooling.

At ProofMatcher, we run a marketplace for premium website templates — think animated, interactive modern web templates with live previews. Our stack? React 19, Vite, Tailwind, and Django REST Framework.

Here's why we ditched CRA and what we learned shipping this to production.

The Problem: CRA Can't Keep Up

When you're building a template marketplace, you're basically shipping a gallery of mini-apps. Each template has:

  • Live previews (often with Three.js or GSAP)
  • Custom animations
  • Heavy asset loading
  • SEO requirements

CRA's dev server started choking around 20+ templates. Cold starts took 30+ seconds. HMR felt random. Our team was spending more time waiting than coding.

Why Vite Won

Vite's dev server uses ESM natively. No more bundling everything upfront. Your browser fetches modules as needed.

The difference is night and day:

  • Cold starts: ~1s vs 30s
  • HMR updates: Instant vs "is it working?"
  • Memory usage: ~500MB vs 2GB+

Here's our base config:

// vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  server: {
    proxy: {
      '/api': 'http://localhost:8000'
    }
  },
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom'],
          three: ['three'],
          ui: ['framer-motion', 'lucide-react']
        }
      }
    }
  }
})
Enter fullscreen mode Exit fullscreen mode

React 19 in Production

Yes, we're running React 19. No, it's not "unstable." The React team's been releasing canary builds for ages, and the Vite plugin handles it beautifully.

The real win? React Server Components aren't mandatory. You can use the new features (like Actions) without buying into the full RSC architecture.

Our async setup with Django:

// Using React 19's use() with Suspense
async function fetchTemplate(id) {
  const res = await fetch(`/api/templates/${id}/`)
  return res.json()
}

function TemplatePreview({ id }) {
  const template = use(fetchTemplate(id))

  return (
    <div>
      <h1>{template.name}</h1>
      <iframe src={template.previewUrl} />
    </div>
  )
}

// Wrap with Suspense where used
<Suspense fallback={<TemplateSkeleton />}>
  <TemplatePreview id={123} />
</Suspense>
Enter fullscreen mode Exit fullscreen mode

Django + Vite: The Proxy Magic

We keep frontend and backend completely separate. Django handles:

  • Authentication (JWT via SimpleJWT)
  • Database models
  • Stripe webhooks
  • File uploads (S3 presigned URLs)

Vite proxies API requests during development, so no CORS issues:

// In Django settings.py
CORS_ALLOWED_ORIGINS = [
    "http://localhost:5173",  # Vite dev server
    "https://proofmatcher.com",
]

# And for production:
STATICFILES_DIRS = [
    BASE_DIR / "frontend-dist",  # Built Vite assets
]
Enter fullscreen mode Exit fullscreen mode

Performance Wins That Matter

1. Chunking Strategy

We manually split Three.js from our main bundle. Users don't pay for 3D unless they view a 3D template.

2. Image Optimization

Using Vite's built-in image handling:

import templateImage from './assets/template.jpg?w=800&format=webp'
// Generates multiple sizes, webp format
Enter fullscreen mode Exit fullscreen mode

3. CSS That Doesn't Block

Tailwind + Vite's JIT mode means CSS updates are instant. No more PostCSS rebuild delays.

The Iframe Preview Solution

This was our trickiest problem: how to preview templates without style collisions.

Solution: Each preview runs in a sandboxed iframe:

<!-- Template preview component -->
<div class="preview-container">
  <iframe
    sandbox="allow-scripts allow-same-origin"
    src={`/template-previews/${templateId}/`}
  />
</div>
Enter fullscreen mode Exit fullscreen mode

Vite builds these previews as separate mini-apps in /public. Zero runtime cost for the main app.

SEO Without SSR

We get this question a lot: "How do you handle SEO without Next.js?"

Honestly? Good old <meta> tags and smart URL design. Django pre-renders critical pages (homepage, categories), and React takes over after load.

Our SEOHead component:

function SEOHead({ title, description, image }) {
  return (
    <>
      <title>{title} | ProofMatcher</title>
      <meta name="description" content={description} />
      <meta property="og:image" content={image} />
      <link rel="canonical" href={window.location.href} />
    </>
  )
}
Enter fullscreen mode Exit fullscreen mode

For a marketplace, Google cares more about page speed and user experience than perfect SSR. Our Lighthouse scores:

  • Performance: 98
  • SEO: 100
  • Accessibility: 97

Would We Do It Again?

Absolutely. Our developer experience improved dramatically:

Metric CRA Vite
Dev server start 30s 1.2s
HMR update 2-5s <100ms
Production build 4min 45s
Bundle size (homepage) 450KB 180KB

The team ships features faster. Our templates load quicker. Users stay longer.

Getting Started Yourself

If you want to try this stack:

# Frontend
npx create-vite@latest myapp --template react
cd myapp
npm install

# Backend
pip install django djangorestframework django-cors-headers
django-admin startproject backend .
Enter fullscreen mode Exit fullscreen mode

Check out Vite's docs and Django REST Framework. Both have fantastic communities.

Wrapping Up

CRA served its purpose. But for modern apps with complex UIs, Vite is just better. Faster dev server, smaller bundles, better DX.

We're open sourcing our base template if you want to see the exact setup. It includes:

  • React 19 + Vite config
  • Django API setup
  • Three.js chunking
  • Iframe preview system

What's your stack look like? Still on CRA or moved to something else?

Top comments (0)