Your React application works perfectly on localhost.

You run the production build, upload it to your server, open the website and…

Nothing. Just a blank white page.

This is one of those React problems that can look much worse than it actually is.

A blank page usually doesn’t mean React completely failed to deploy. More often, the browser downloaded something, but a JavaScript error, incorrect asset path, routing problem, missing environment variable or API failure prevented the application from rendering correctly.

Instead of rebuilding the entire project or randomly changing hosting settings, let’s troubleshoot the problem systematically.


Why Does a React App Show a Blank Page After Deployment?

A React application can show a blank page after deployment because of several different issues:

  • JavaScript runtime errors
  • Incorrect asset or base paths
  • Missing production build files
  • Wrong environment variables
  • React Router configuration
  • Server rewrite configuration
  • API or CORS errors
  • Incorrect deployment directory
  • Case-sensitive imports
  • Cached old application files

The important thing is to determine whether the problem is happening during:

Build → Asset loading → JavaScript execution → Routing → API communication → Rendering

Once you know which stage is failing, the problem becomes much easier to solve.


1. Check the Browser Console First

Before changing your React code, open the deployed application in Chrome or another browser.

Open:

Developer Tools → Console

On Chrome you can usually press F12, Ctrl + Shift + I, or right-click the page and choose Inspect.

Look for red errors.

For example:

Uncaught TypeError: Cannot read properties of undefined

or:

Failed to load resource: the server responded with a status of 404

or:

Uncaught SyntaxError: Unexpected token '<'

or:

Access to fetch at ... has been blocked by CORS policy

These messages are far more useful than the blank screen itself.

A white page is only the symptom.

The browser console often tells you the actual problem.


2. Check the Network Tab

If the console doesn’t immediately explain the issue, open:

Developer Tools → Network

Refresh the page.

Look for failed requests, particularly:

  • JavaScript files
  • CSS files
  • API requests
  • Images
  • JSON/config files

Pay attention to HTTP responses such as:

404

403

500

If your JavaScript bundle returns 404, React may never start.

For example, your HTML might request:

/assets/index-AbCd123.js

while the actual application is deployed under:

/my-app/assets/index-AbCd123.js

That’s not really a React component problem.

It’s a deployment/base-path problem.


3. Make Sure You Deployed the Production Build

A surprisingly common deployment mistake is uploading the wrong directory.

Normally you first run:

npm run build

What gets generated depends on your React tooling.

For a Vite application, the default output directory is commonly:

dist/

Create React App traditionally generates:

build/

You generally deploy the generated production files, not simply upload your entire src directory and expect the browser to run it.

For Vite, a typical deployment contains files similar to:

dist/
├── index.html
└── assets/
    ├── index-xxxxx.js
    └── index-xxxxx.css

Verify that the files generated by your latest build are actually the files deployed to production.


4. Test the Production Build Locally

Before blaming the hosting server, test the production build.

For Vite, you can commonly use:

npm run build
npm run preview

If the production build already shows a blank page locally, the hosting server probably isn’t your first problem.

If it works with the production preview but fails after deployment, investigate differences between:

local production preview vs live hosting

That narrows the search considerably.


5. Check the Base Path in Vite

This is one of the first things to inspect when a Vite React app works locally but fails after being deployed into a subdirectory.

Suppose your application is hosted at:

https://example.com/customer-app/

instead of:

https://example.com/

Your assets need to resolve correctly from that deployment location.

Vite supports a base configuration in vite.config.js.

For example:

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
    plugins: [react()],
    base: '/customer-app/',
});

Then rebuild:

npm run build

and deploy the newly generated output.

Don’t simply change vite.config.js on the server and expect existing build files to update.

The application must be rebuilt.


6. Check Create React App’s Deployment Path

If you’re maintaining an older Create React App project, deployment-path configuration may also affect generated asset URLs.

For example, CRA projects sometimes use the homepage field in package.json to control deployment paths.

A project deployed at a subdirectory needs configuration appropriate for that actual location.

The exact solution depends on your application and deployment strategy, so don’t copy a random homepage value without understanding where the app is being served.


7. Inspect the Generated index.html

Open your production index.html.

Look at the generated JavaScript and CSS URLs.

For example:

<script type="module" src="/assets/index-abc123.js"></script>

Now request that URL directly from the production website.

Does it return the JavaScript file?

Or does it return:

  • 404 page
  • Hosting error
  • Your React index.html
  • Login page
  • Server-generated HTML

This test is particularly useful for errors such as:

Unexpected token '<'

Sometimes the browser expects JavaScript but the server returns an HTML document instead.

The browser then tries to parse HTML as JavaScript and fails.


8. Check React Router

Another common deployment problem appears when using client-side routing.

Suppose your application has:

/
/login
/dashboard
/profile

Navigating inside the application works.

But refreshing:

https://example.com/dashboard

produces a server 404 or blank/error page.

Why?

React Router understands /dashboard.

Your Apache or Nginx server may not.

The server receives a request for /dashboard and tries to find a physical file or directory with that name.

For a typical single-page application using browser history routing, the server usually needs to fall back to:

index.html

for routes that should be handled by React.


9. React Router on Apache

If your React SPA is hosted on Apache, rewrite configuration may be required.

A common concept is:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /

    RewriteRule ^index\.html$ - [L]

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d

    RewriteRule . /index.html [L]
</IfModule>

But don’t blindly paste this into every server.

If your React application is hosted inside a subdirectory, the rewrite base and target may need to reflect that deployment.

Also be careful when React is hosted alongside WordPress, Laravel or another application. An overly broad rewrite rule can interfere with the other application.


10. React Router on Nginx

The same concept applies to Nginx.

For a typical SPA, configuration often needs to attempt the requested resource and then fall back to index.html.

Conceptually:

location / {
    try_files $uri $uri/ /index.html;
}

Your actual configuration depends on where the application is hosted and what else the server is serving.

After modifying Nginx configuration, validate it before reloading the service.


11. Check Your Environment Variables

This is another major reason a React application works locally but fails in production.

Locally you might have:

.env

containing your API URL.

But the production build may not receive the same environment variable.

For Vite, client-exposed environment variables conventionally use the VITE_ prefix.

For example:

VITE_API_URL=https://api.example.com

Then:

const apiUrl = import.meta.env.VITE_API_URL;

If VITE_API_URL is missing during the production build, your application may attempt requests using an undefined or incorrect URL.

Remember:

Frontend environment variables are usually incorporated during the build process.

Changing .env after the application has already been built won’t necessarily change the generated JavaScript bundle.

After changing build-time environment configuration:

npm run build

again.


12. Don’t Put Secrets in React Environment Variables

An important security point:

Variables exposed to browser-side React code are not private simply because they’re stored in .env.

If the application needs a value in the browser, assume users can inspect it.

Don’t put sensitive server-side secrets such as:

  • Private API secrets
  • Database passwords
  • Server credentials
  • Private signing keys

inside client-side React environment variables.

Secrets belong on your backend.


13. Check Whether the API URL Still Points to Localhost

This happens more often than you’d expect.

Your application works locally because it calls:

http://localhost:8000/api

You deploy React.

But the production build still calls:

http://localhost:8000/api

On a visitor’s computer, localhost means their computer, not your production API server.

Your production environment should point to the appropriate live API endpoint.

Use the Network tab to see exactly which URL the deployed application is requesting.

Don’t assume your environment configuration was loaded correctly.


14. Check for CORS Errors

Suppose your frontend is hosted at:

https://app.example.com

and your API is hosted at:

https://api.example.com

The browser enforces cross-origin rules.

If the backend isn’t configured to permit the required origin/methods/headers, you may see a CORS error.

For example:

blocked by CORS policy

This isn’t normally solved by randomly adding headers to your React application.

CORS policy is primarily enforced based on the server’s response.

Investigate the API/backend configuration.

We’ll cover CORS troubleshooting separately in our upcoming Express/Node.js article.


15. Make Sure Your UI Handles API Failures

An API failure shouldn’t ideally turn your entire application into a blank page.

Consider code that assumes data always exists:

return users.map((user) => (
    <div key={user.id}>
        {user.name}
    </div>
));

If users unexpectedly becomes undefined, rendering may fail.

Your application should account for:

  • Loading state
  • Empty state
  • Error state
  • Unexpected API responses

For example:

if (loading) {
    return <p>Loading...</p>;
}

if (error) {
    return <p>Unable to load data.</p>;
}

if (!Array.isArray(users)) {
    return <p>No users available.</p>;
}

Production APIs fail sometimes.

Your UI should fail gracefully rather than displaying an unexplained white screen.


16. Check Case-Sensitive Imports

This is a classic deployment issue.

On a local environment, you might have:

components/Header.jsx

but import:

import Header from './components/header';

Some development environments may tolerate filename case differences.

A Linux production server may not.

Header.jsx

and:

header.jsx

are not necessarily the same filename.

Review import paths when the build or production environment reports missing modules/files.


17. Check for JavaScript Errors That Only Happen in Production

Production builds can expose assumptions that weren’t obvious during development.

Check for:

  • Undefined variables
  • Null values
  • Incorrect API response assumptions
  • Environment-dependent code
  • Browser API differences
  • Third-party script failures
  • Minification/build issues
  • Incorrect dynamic imports

Again, start with the browser console.

Don’t debug a blank React page while ignoring a clear exception sitting in DevTools.


18. Check Lazy Loading and Dynamic Imports

Suppose you’re using:

const Dashboard = React.lazy(
    () => import('./pages/Dashboard')
);

The initial page might load correctly, but navigating to Dashboard fails because its generated chunk can’t be downloaded.

Check Network for failed JavaScript chunk requests.

This can happen after deployments when:

  • Old HTML is cached
  • New build removed old hashed chunks
  • CDN still serves stale files
  • Service worker has an older application version
  • Asset paths changed

A hard refresh may appear to solve the problem for you, but don’t assume every user’s cache will behave the same way.

Your deployment/cache strategy should handle versioned assets correctly.


19. Clear Browser, CDN and Hosting Cache

Caching can create a confusing combination:

Old index.html + new JavaScript files

or:

New index.html + old cached assets

If you use:

  • Browser caching
  • Cloudflare/CDN
  • Hosting cache
  • Reverse proxy
  • Service worker/PWA caching

make sure you’re testing the current deployment.

Use an incognito/private window as a quick comparison, but treat it as a diagnostic step rather than the permanent solution.


20. Check the Browser Console for Mixed Content

Suppose your React website uses:

https://example.com

but the API request goes to:

http://api.example.com

The browser may block insecure content loaded from a secure HTTPS page.

Check DevTools for mixed-content warnings.

In production, use properly configured HTTPS endpoints.


21. Check Authentication and Redirect Logic

Sometimes the application isn’t technically blank.

It’s stuck in broken navigation logic.

For example:

App starts
↓
Check token
↓
Redirect to login
↓
Login detects token
↓
Redirect to dashboard
↓
Dashboard rejects session
↓
Redirect to login

This can create loops, flashes or seemingly blank screens.

Check:

  • Authentication state
  • Token storage
  • Token expiry
  • API session validation
  • Protected route logic
  • Redirect conditions

Add controlled logging during development to understand which route/state is repeatedly changing.


22. Check Your Root Element

React needs the correct DOM element to mount the application.

Your HTML may contain:

<div id="root"></div>

while your application expects:

document.getElementById('root')

If the IDs don’t match, React can’t mount where expected.

This isn’t the most common deployment-only issue, but it’s worth checking if index.html was customized during deployment.


23. Check Deployment Directory Structure

Let’s say you want the application available at:

https://example.com/app/

but upload your files as:

public_html/
    app/
        dist/
            index.html
            assets/

Your actual URL may then effectively require:

/app/dist/

instead of /app/.

Normally you want the contents of the generated output directory placed in the intended web root for that application, not necessarily the output directory itself.

Always verify where index.html actually lives relative to the public URL.


24. React App Works on / but Refreshing /dashboard Fails

This deserves its own example because it’s extremely common.

Suppose:

https://example.com/

works.

You click Dashboard.

React Router navigates to:

https://example.com/dashboard

Everything works.

Now press Refresh.

You get 404.

That strongly suggests:

React Router is working, but your web server doesn’t have SPA fallback routing configured correctly.

Investigate Apache/Nginx/hosting rewrite rules rather than rewriting your React Dashboard component.


25. React App Works Locally but Is Blank on Production

Here’s a practical troubleshooting sequence.

Step 1

Open DevTools Console.

You see:

Failed to load resource: 404

for:

/assets/index-abc123.js

Step 2

Open Network.

The JavaScript asset really is returning 404.

Step 3

Check deployment URL.

Your application is hosted at:

https://example.com/client/

but generated assets point to:

https://example.com/assets/

Step 4

Correct the Vite base configuration:

export default defineConfig({
    plugins: [react()],
    base: '/client/',
});

Step 5

Rebuild:

npm run build

Step 6

Deploy the new dist output.

The application loads.

The problem wasn’t:

“React doesn’t work on the server.”

It was:

Incorrect production asset paths.


26. Example: React Page Blank Because of API Failure

Another scenario:

Your app loads, but the main component depends on an API request.

DevTools shows:

GET http://localhost:8000/api/products

Production visitors obviously can’t access your development API.

You inspect the environment configuration and discover the production API variable wasn’t available during the build.

Correct the environment configuration, rebuild and redeploy.

Again, the blank page is only the visible symptom.


React Blank Page Troubleshooting Checklist

If your React application shows a blank page after deployment, check these in order:

  • Open the browser console
  • Check Network for failed assets
  • Confirm the production build completed successfully
  • Test the production build locally
  • Verify the correct build directory was uploaded
  • Check generated JavaScript/CSS paths
  • Verify Vite base configuration
  • Check CRA deployment configuration if applicable
  • Verify React Router fallback configuration
  • Check production environment variables
  • Verify the production API URL
  • Check CORS errors
  • Check HTTPS/mixed-content problems
  • Review case-sensitive imports
  • Check lazy-loaded chunks
  • Clear browser/CDN/hosting caches
  • Check authentication redirects
  • Verify the React root element
  • Check the deployment directory
  • Rebuild and redeploy after configuration changes

The key is to diagnose the failure in layers instead of changing everything at once.


How to Prevent React Deployment Problems

Test the Production Build Before Deployment

Don’t rely only on:

npm run dev

Test what you’re actually going to deploy.

Maintain Separate Environment Configuration

Keep development and production API URLs clearly separated.

Use a Repeatable Deployment Process

Avoid manually uploading random files from different builds.

Check the Browser Console After Every Deployment

A deployment isn’t finished just because the upload completed.

Add Error Handling

Your entire application shouldn’t become unusable because one API request failed.

Use Error Boundaries Where Appropriate

React error boundaries can help prevent certain rendering errors from taking down larger portions of the UI and can provide a better fallback experience.

Monitor Production Errors

For important applications, production error monitoring can help you discover frontend exceptions before users start reporting blank screens.


Final Thoughts

A React blank page after deployment can feel like a hosting disaster, especially when the application works perfectly locally.

But the problem usually becomes much clearer once you stop looking at the white page and start looking at:

Console → Network → Build → Paths → Environment → Router → API → Server

Start with the browser’s error messages.

Determine whether JavaScript assets are loading.

Verify the production configuration.

Then investigate routing and API communication.

A systematic troubleshooting process is faster and safer than repeatedly rebuilding the project and hoping the problem disappears.


Need Web Application Help?

Still Seeing a Blank Page After Deploying React?

Production React issues can involve multiple layers: frontend code, Vite/build configuration, React Router, APIs, CORS, authentication, Apache/Nginx and hosting configuration.

  • React deployment troubleshooting
  • React and Next.js development
  • Node.js and Express APIs
  • REST API integrations
  • Authentication issues
  • Performance optimization
  • Existing application debugging
  • Custom web application development
Discuss Your React Project →