# Deploying React with Vercel

**Author:** Vercel

---

Deploy React with Vercel by pushing to Git or using the Vercel CLI. Framework detection maps your project to build defaults, preview deployments give every pull request its own URL, Fluid compute prices server rendering by active CPU, and Partial Prerendering combines cached and dynamic content in one response.

A React app is never one thing. The same `package.json` can describe a static single-page application (SPA), a server-rendered app, a streaming React Server Components tree, or a hybrid that caches a shell and renders the rest per request. Whatever you build deploys correctly only if the pipeline knows which of those it's looking at. Self-hosting, that knowledge is your job, because you wire the build tool, the CDN, the SSL, and the runtime to agree on it. On Vercel, framework detection and the build do the mapping, so you stop maintaining the glue and start shipping the app.

## Key takeaways

- A React deploy is a mapping from source to runtime primitives, not a single build step, and the platform that owns the mapping is the one you stop maintaining by hand.
  
- Framework detection applies correct build defaults for dozens of frameworks, so most React projects deploy with no configuration.
  
- Per-PR preview deployments replace shared staging with isolated, production-equivalent environments.
  
- Fluid compute bills active CPU separately from I/O wait, which is what makes streaming and server-rendered React economical at scale.
  
- Partial Prerendering, stable in Next.js 16 through Cache Components, serves a cached static shell and streams the dynamic holes in one request, so a page can be both cacheable and personalized.
  

## Stop wiring a pipeline and let the build map your React app

Treat deploying React as a translation problem the platform solves rather than a build step you configure. A self-hosted React deployment is a stack of tools assembled by hand:

- A build tool produces the assets
  
- A CI pipeline runs the build
  
- A CDN serves the static files
  
- SSL provisioning terminates TLS
  
- A serverless or container runtime executes anything dynamic
  

Each of those has its own configuration, and a change to one usually forces a change in another. Teams often spend more engineering hours keeping that stack in agreement than they spend on the application it serves.

That stack gets expensive because it has to encode, manually, which rendering mode every route uses. Vercel moves that decision into the build instead. When you push a React project, the platform inspects your package files, configuration, and directory structure to detect the framework in use.

The detected framework sets the defaults. A Vite app, a Create React App project, a React Router app with server rendering, and a full Next.js setup each get different build defaults without you setting them. Framework detection covers dozens of frameworks, which means the common case needs no configuration at all.

What the build produces is a small set of runtime primitives:

- Static assets that replicate across Vercel's CDN and cache close to users after the first request
  
- Vercel Functions that run dynamic logic in compute regions near your data
  
- Routing rules that send each request to the right one of those two
  

Images optimize on demand rather than at build time, which keeps builds fast while improving load performance and Core Web Vitals, and SSL certificates provision and renew themselves for every domain. None of that is configuration you write, because it's the mapping the build infers.

The limit is that detection follows convention. If your project does something the framework's conventions don't express, you override the defaults through a `vercel.json` file and set the build command directly. That escape hatch exists because convention-based mapping has an edge, and you tend to find that edge the moment your project lives outside the convention.

## Push to Git and replace your deployment pipeline

Once the mapping lives in the build, your deployment interface becomes a Git push. Push a React project to GitHub, GitLab, or Bitbucket, and the detection-to-primitives sequence runs on its own: detect the framework, apply the defaults, build, and deploy.

The anti-pattern this replaces is the one where every deploy is a configuration negotiation. A self-hosted pipeline asks you to keep the build tool, the CI runner, and the runtime in sync by hand, and the failures from that work show up later, when a dependency bump in one layer quietly breaks an assumption in another and nobody remembers which knob set it. Moving the defaults into the build removes the negotiation for projects that follow convention.

When Git isn't your trigger, the CLI deploys the same way from a terminal:

`npm i -g vercel vercel --prod vercel env pull`

The first two commands deploy directly without any Git integration, and `vercel env pull` writes the project's environment variables into a local `.env` file so your development environment matches what production runs. Teams that need to customize the build still reach for `vercel.json` and the build command override, but for projects on the framework's conventions, there's nothing to configure before the first deploy.

## Give every pull request its own environment instead of shared staging

The most expensive habit in React deployment is treating a shared staging environment as a production rehearsal. It isn't one, and the reason is mechanical. A shared staging server takes grouped changes from several engineers and serves them through a single URL, which produces three failures the team usually blames on bad luck:

- The environment drifts from production over time, so passing in staging stops meaning passing in production.
  
- In-flight changes from different engineers collide with each other in the one shared URL.
  
- Feedback from designers or product managers lands after the relevant code has already been merged or overwritten.
  

That workflow tests a state that exists nowhere else, rather than rehearsing production.

### Move the unit of deployment to the pull request

Preview deployments fix that by changing the unit of deployment from the environment to the pull request. Every push to a branch with an open PR generates a unique, shareable URL running on the same infrastructure as production. Designers, product managers, and engineers review the application in its actual deployed state instead of a screenshot or a Figma mock.

Review happens in place, too. Preview deployments carry inline commenting, so a reviewer starts a thread, shares a screenshot, or sends a notification directly on the rendered UI, and the feedback stays pinned to the component it's about rather than scattered across a separate channel.

### Scope what previews can reach

The tradeoff is blast radius. A preview environment that can reach production-grade APIs or rate-limited services is convenient until it quietly burns a quota or runs up a bill, so scope which backends each environment is allowed to hit before you wire previews into anything metered. The per-PR model gives you isolation cheaply, and you keep that isolation only if the previews can't reach into shared production state.

## Stream server-rendered React without paying for I/O wait

Server-rendered React has a cost-model problem that duration-based serverless billing makes worse. When wall-clock time is the billed unit, a React Server Component that spends 200 milliseconds of CPU and then waits 800 milliseconds on a database response bills for the full second. Across millions of requests, the time spent waiting on I/O becomes a large share of the bill. You're paying for idleness.

Fluid compute changes that allocation by letting a single function handle multiple requests at once, using the idle I/O wait from one request to serve another on the same instance. Active CPU billing then charges only for active CPU time and bills memory-only periods at a lower rate. That is what makes streaming workloads economical at scale, where a function holds a connection open while it waits for data.

### Streaming is the rendering model, not an add-on

Streaming matters here because it's the underlying rendering model for React Server Components, not an optional optimization layered on top. Server Components fetch their data and render entirely on the server, and the resulting HTML streams into the client-side React tree, which removes the client-side re-render.

That streaming is also ordered. Components that don't depend on data, or that carry higher priority, get sent first so React can start hydration earlier, while lower-priority components arrive in the same server request once their data resolves.

On Vercel, this works with no code changes, because Vercel Functions speak HTTP and streaming responses work out of the box. Self-hosting Node.js, that behavior is yours to own, including backpressure handling and proxy buffering.

Cold starts are the other tax on server-rendered React, and Vercel cuts them through two mechanisms:

- **Bytecode caching.** On Node.js 20 or higher, Vercel Functions store the compiled bytecode of JavaScript files after the first execution, which lowers cold start time on later invocations.
  
- **Function pre-warming.** Production deployments pre-warm function instances, and Fluid compute routes requests to existing warm instances before creating new ones.
  

Neither mechanism asks anything of your application code, which is the recurring theme: the runtime behavior that you'd otherwise hand-tune is part of the platform's mapping from your source to how it runs.

## Combine static and dynamic rendering with Partial Prerendering

React rendering has historically forced a choice between static generation, which is fast and cacheable but can't personalize, and server rendering, which is dynamic but slower per request. Partial Prerendering (PPR) refuses the choice, pre-generating the static portions of a page and serving them from cache while the dynamic portions stream into the same response.

PPR became stable in Next.js 16 through Cache Components. With Cache Components, data is dynamic by default, and you choose what to cache at the page, component, or function level with the `use cache` directive. The sequence at request time:

1. The static shell is served immediately from cache, with holes where dynamic content belongs.
   
2. The dynamic portions render in Vercel Functions and stream into the holes.
   
3. The holes load in parallel, which lowers total perceived load time.
   

On Vercel, PPR uses Incremental Static Regeneration (ISR) for the static shell and Vercel Functions for the dynamic parts, so a PPR route incurs ISR reads and writes plus function invocations. You control how long cached content stays fresh with `cacheLife` and invalidate it on demand with `cacheTag`.

Use PPR when a page is mostly static but has parts that change per request or per user. Product and catalog pages fit, where a static layout carries a live price or cart contents, as do dashboards, where a cached layout wraps a personalized greeting or notification count.

### Skip the container layer unless your workload needs it

Containers are the layer most teams add out of habit and rarely need here. For most React applications on Vercel, the container layer is pure overhead, because a React app's deployment requirements are well-defined. The app needs four things:

- Built assets
  
- Requests routed to the right resources
  
- Static content cached at the edge
  
- Server functions run when needed
  

Wrapping that in Docker adds base images, security patches, and orchestration configuration without adding any application capability. The serverless model already provisions server resources only while users are making requests, so idle traffic costs nothing and spikes scale without your intervention. Container-based architectures ask you to maintain each container and usually reach for an orchestrator like Kubernetes to scale, where serverless scaling is automatic.

The recommendation comes with a boundary. Containers remain the right call for workloads outside what Vercel Functions accommodate:

- Long-lived stateful processes
  
- Runtimes with constraints the functions don't support
  
- Cases where the React app must be colocated with non-frontend services under a single orchestrator
  

Vercel also supports deploying a project as a container image built from a Dockerfile, so a workload that genuinely needs a container doesn't force you off the platform. And plenty of teams self-host Next.js deliberately, because the framework runs anywhere. The question is whether the maintenance a container costs you buys capability you need, and for most React apps it doesn't.

## Confirm the deploy behaved

The fast check is the preview URL itself, since every PR gives you a production-equivalent environment to open before merge. After promotion, three places confirm production behavior:

- The deployment's details page shows the build output, the routes it produced, and the functions it created, so you can verify the mapping matched your intent.
  
- Runtime Logs show function invocations, errors, and status codes per route.
  
- Speed Insights and Observability track Core Web Vitals and function behavior over time, which is where rendering-strategy changes like PPR show up as measurable movement rather than a feeling.
  

Read against the self-hosted baseline, the contrast is what each concern costs you to own:

| Concern                   | Self-hosted React                                          | React on Vercel                                         |
| ------------------------- | ---------------------------------------------------------- | ------------------------------------------------------- |
| Build configuration       | Hand-wired build tool, CI, and runtime kept in sync        | Framework detection applies defaults automatically      |
| Pre-merge review          | Shared staging that drifts and batches conflicting changes | A production-equivalent preview URL per pull request    |
| SSL                       | Provisioned and renewed by the team                        | Provisioned and renewed automatically per domain        |
| Scaling                   | Orchestrator like Kubernetes, manually tuned               | Automatic, with idle traffic costing nothing            |
| Streaming and cold starts | Your responsibility, including backpressure and buffering  | Streaming out of the box, bytecode caching, pre-warming |
| Container upkeep          | Base images, patches, orchestration config                 | Not required for most React apps                        |

Every row in that table is a place where the platform owns the mapping you would otherwise own by hand.

## Ship React on Vercel: the four choices that map source to runtime

Framework detection, preview deployments, Fluid compute, and Partial Prerendering are one decision applied four times: map a React project's source to the right runtime behavior so your team never hand-maintains the mapping.

- **Framework detection** maps source to build defaults with no configuration for projects on convention.
  
- **Preview deployments** map a pull request to a production-equivalent environment on the same infrastructure as production.
  
- **Fluid compute** maps a streaming workload to a cost model that doesn't bill idleness.
  
- **Partial Prerendering** maps a single page to both cached and dynamic rendering in one response.
  

To put these into practice, [deploy a new project](https://vercel.com/new) or start from a [React template](https://vercel.com/templates). The fastest way to see the mapping work is to push a project and open the preview URL it gives you back.

## Frequently asked questions about deploying React with Vercel

### Does Vercel only support Next.js for React deployments?

No. Vercel supports React applications built with Vite, Create React App (now deprecated by the React team but still supported as a preset), React Router with server rendering or SPA mode, Remix, Gatsby, RedwoodJS, TanStack Start, and other React-based frameworks. Next.js gets the deepest integration because Vercel maintains it, but framework detection applies defaults for dozens of frameworks, so the platform isn't a Next.js-only target.

### Do I need to configure anything for a Vite-based React SPA?

For most projects, no, because Vercel detects Vite automatically and applies the correct build settings. One exception bites SPAs specifically: when a Vite app is configured as a single-page application, deep linking won't work out of the box, and you need a `vercel.json` rewrite that routes all paths to the index page:

`{ "rewrites": [{ "source": "/(.*)", "destination": "/index.html" }] }`

To read Vercel system environment variables during the build, prefix the variable name with `VITE_`.

### How does Vercel handle traffic spikes for React applications?

Fluid compute, enabled by default for new projects, scales automatically with traffic. Functions scale out as request volume rises, and in the event of regional downtime, traffic is automatically rerouted to the next closest region, so spikes and failures are handled without manual intervention.

### Can I deploy React on Vercel without using Git?

Yes. The Vercel CLI deploys from the terminal without any Git integration: install it with `npm i -g vercel`, then run `vercel --prod`. The CLI also manages environment variables through commands like `vercel env pull`, which writes the project's variables into a local `.env` file.

---

[View full KB sitemap](/kb/sitemap.md)
