Introduction to React Deployment
React deployment is the process of preparing an application for production and making it accessible to users over the internet. During development, your application typically runs on a local development server. Deployment creates an optimized production build and publishes its files to a hosting environment.
React applications created with tools such as Vite usually produce static HTML, JavaScript, CSS, and other assets. These files can be hosted on platforms such as Netlify, Vercel, or static website hosting services. Applications that require server-side rendering or a backend need an appropriate server or hosting architecture as well.
Understanding the Deployment Process
A typical React deployment follows a series of steps from local development to a production release.
- Complete development and verify the application locally.
- Run linting, type checking, and automated tests where configured.
- Create an optimized production build.
- Configure environment-specific settings and API endpoints.
- Upload or publish the generated build to a hosting provider.
- Configure the domain, HTTPS, routing, and any required server rules.
- Verify the deployed application and monitor errors or performance issues.
The exact process depends on the build tool, hosting provider, and whether the application is a static single-page app or uses server-side rendering. For initial project configuration, see React Setup.
Creating a Production Build with Vite
In a typical Vite-based React project, the build command compiles the application and generates optimized production assets in the dist directory.
npm install
npm run build
The build output commonly contains an HTML entry point and generated JavaScript, CSS, and asset files. The exact files depend on your project and build configuration.
To preview the production build locally using Vite, run:
npm run preview
The preview server is useful for checking the generated output before publishing. It is intended for local verification, not as a production hosting server.
Understanding the dist Directory
After a successful Vite build, the generated files are normally placed in dist. Your hosting provider serves these files to browsers.
my-react-app/
src/
public/
package.json
vite.config.ts
index.html
dist/
index.html
assets/
index-example.js
index-example.css
The filenames shown here are illustrative; Vite commonly generates hashed asset filenames. In most deployments, you publish the contents of dist rather than the source directory.
Keep source code and build output conceptually separate. Hosting the source directory directly does not automatically produce the optimized application that your users should receive.
Deploying React to Netlify
Netlify supports static React deployments and can build a project automatically from a connected Git repository. This is useful when you want updates to be published whenever changes are pushed to the configured branch.
- Push your React project to a Git provider supported by Netlify.
- Create a new site and connect the repository.
- Set the build command to
npm run build. - Set the publish directory to
distfor a standard Vite project. - Configure required environment variables in the site's build settings.
- Deploy and test the generated site URL.
If you use a different build tool, verify its output directory rather than assuming it is dist. For example, a Create React App project commonly uses build.
Official resource: Netlify Documentation.
Deploying React to Vercel
Vercel supports Git-based deployments and can detect many frontend frameworks automatically. It can build and publish a React application whenever changes are pushed to a connected repository.
- Push the application to your Git repository.
- Import the repository into Vercel.
- Review the detected framework and build settings.
- Configure environment variables for the relevant deployment environment.
- Deploy the project and verify the generated URL.
- Configure a custom domain if required.
Vercel can also support server-rendered applications when the framework and project configuration require it. Choose the deployment model that matches your application rather than treating every React project as a static site.
Official resource: Vercel Documentation.
Configuring Environment Variables
Applications commonly use different configuration values during local development and production. For example, the API URL used locally may differ from the production API URL.
In a Vite application, client-side environment variables intended for application code normally use the VITE_ prefix.
# .env.development
VITE_API_BASE_URL=http://localhost:5000/api
# .env.production
VITE_API_BASE_URL=https://api.example.com/api
Read the configured value from your application with import.meta.env.
const apiBaseUrl = import.meta.env.VITE_API_BASE_URL;
async function getProducts() {
const response = await fetch(apiBaseUrl + '/products');
if (!response.ok) {
throw new Error('Unable to load products');
}
return response.json();
}
Vite replaces these variables during the build. Any variable exposed to client-side code can be inspected by users in the generated assets. Never place passwords, private API keys, database credentials, or other secrets in client-side environment variables.
Environment variables configured on a hosting provider generally need to be available when the application is built. Updating a variable may require a new deployment before the generated assets reflect the change.
Configuring React Router for Production
Single-page applications commonly use client-side routing. A route such as /dashboard may work when navigating from the home page but fail when a user opens it directly in a new tab.
This happens when the hosting server attempts to find a physical file at that path instead of returning the React application's entry HTML. For history-based routing, configure the host to serve index.html for application routes while allowing real static assets to be served normally.
For example, a Netlify single-page application can use a _redirects file in the public assets directory:
/* /index.html 200
This is a standard fallback pattern for single-page apps, but review your hosting configuration and existing rules before adding it. Server-rendered applications and applications with server-managed routes need a configuration appropriate to their architecture.
Learn about client-side routing in React Router.
Using a Custom Domain and HTTPS
A custom domain gives your application a branded web address. Most modern hosting providers allow you to connect a domain and configure the required DNS records.
- Add the domain in your hosting provider's domain settings.
- Configure the DNS records specified by the provider.
- Wait for DNS changes to propagate.
- Verify domain ownership if requested.
- Enable or confirm HTTPS and test the certificate.
- Choose the preferred canonical domain, such as the apex domain or the
wwwsubdomain.
Use HTTPS for production websites to protect traffic and avoid browser security warnings. If your frontend calls an API on another origin, ensure the API uses HTTPS as well and has the correct cross-origin resource sharing (CORS) configuration.
Handling API Requests and CORS
A deployed frontend often communicates with a separate backend. Even when the frontend works locally, production API calls can fail because of an incorrect endpoint, blocked CORS request, invalid authentication configuration, or an unavailable backend.
Before releasing the application, verify that:
- The production API URL points to the correct environment.
- The backend is reachable over HTTPS.
- The backend allows the production frontend origin when cross-origin requests are required.
- Authentication callbacks and allowed origins include the correct production domain.
- Errors and failed network requests are handled gracefully in the UI.
- Credentials and secrets remain on the server rather than being embedded in frontend code.
CORS is enforced by browsers and configured on the server that receives the request. Changing the frontend alone cannot grant permission to an API that does not allow its origin.
For implementation patterns, see React API Fetching and React Error Handling.
Optimizing Production Performance
Production builds typically minify JavaScript and CSS and optimize assets. Additional improvements may be needed for large applications with many routes, large dependencies, or media-heavy pages.
- Code splitting: Load parts of the application only when needed.
- Lazy loading: Defer loading suitable routes and components until they are required.
- Asset optimization: Compress images and use appropriate formats and dimensions.
- Dependency review: Remove unused libraries and avoid unnecessarily large packages.
- Caching: Configure static assets for efficient browser and CDN caching.
- Performance measurement: Test real loading behavior and investigate large bundles or slow interactions.
Dynamic imports and React's lazy can help split code into smaller chunks. Use them where the additional loading boundary improves the user experience rather than adding complexity everywhere.
Explore React Lazy Loading and React Performance for more optimization techniques.
Build and Deployment Checks
A successful local development session does not guarantee that the production build will succeed. Add a repeatable verification process before publishing changes.
npm ci
npm run build
npm ci installs dependencies from the lockfile and is useful in automated build environments. Run your project's tests and linting commands as appropriate; not every starter template defines the same scripts.
If your project uses TypeScript, ensure that type checking is included in your validation process. A build tool may transpile TypeScript without necessarily performing a complete type check, depending on the configuration.
npx tsc --noEmit
npm run build
The TypeScript command applies when the project has TypeScript and a suitable tsconfig.json. Review your scripts and build pipeline to avoid assuming every project uses the same setup.
Continuous Deployment with Git
Continuous deployment automates the process of building and publishing changes when updates reach a configured branch or pass required checks. Many static hosting providers support this workflow through repository integrations.
A typical workflow includes:
- Commit and push changes to the repository.
- Run automated linting, type checks, and tests.
- Build the application using the configured production environment.
- Publish a preview or production deployment.
- Verify the deployment and monitor any reported failures.
Use separate preview and production environments when possible. This allows changes to be tested before they replace the public application.
Troubleshooting Common Deployment Issues
Blank page after deployment
Inspect browser console errors, failed network requests, and the generated HTML. Verify the asset paths and the Vite base setting if the application is hosted under a subpath.
Routes return 404 on refresh
Configure an appropriate single-page application fallback for client-side routes. Confirm that the rule does not override API endpoints or prevent real static assets from being served.
API calls fail in production
Check the deployed API URL, HTTPS configuration, CORS policy, authentication settings, and backend logs. Do not assume that a successful local request proves the production endpoint is configured correctly.
Environment variables are missing
Confirm the required variables exist in the hosting provider's build environment, use the correct prefix for the build tool, and trigger a fresh build after changing build-time configuration.
The build fails in CI
Review the build logs, Node.js version, dependency lockfile, TypeScript errors, missing environment variables, and platform-specific assumptions. Reproduce the production build locally when possible.
Old content remains after deployment
Check CDN and browser caching, confirm that the latest build was published, and review cache headers. Hashed assets can usually be cached for a long time, while the HTML entry point should be revalidated so users receive updated asset references.
Production Security Considerations
Deployment is also an opportunity to review the security of the complete application. A React frontend cannot keep secrets private because its client-side code is delivered to users.
- Keep private credentials and privileged API keys on a trusted backend.
- Use HTTPS for production traffic and secure authentication flows.
- Validate authorization and permissions on the server, not only in the UI.
- Configure CORS with the intended origins rather than broadly allowing every origin without a reason.
- Avoid logging passwords, access tokens, or sensitive user data in the browser console.
- Keep dependencies updated and review security advisories relevant to the application.
- Use an appropriate Content Security Policy and other security headers where supported by your hosting architecture.
Hiding a button or protecting a client-side route is not a substitute for backend authorization. Any sensitive operation must be checked by the server that performs it.
Deployment Checklist
Before announcing a production release, verify the essential parts of the application.
- The production build completes successfully.
- Tests, linting, and type checks pass where configured.
- Production environment variables and API endpoints are correct.
- Direct navigation and refresh work for supported application routes.
- API requests, authentication, and error states behave correctly.
- The custom domain and HTTPS configuration are valid.
- Important pages work on mobile and desktop layouts.
- Images, fonts, and other assets load without errors.
- Secrets are not exposed in client-side code.
- Monitoring and rollback procedures are available for production changes.
Key Takeaway
React deployment involves more than uploading a build directory. Build and verify optimized assets, configure environment variables and routing, connect the API securely, enable HTTPS, and test the production application. A repeatable deployment pipeline makes releases more reliable and easier to maintain.