No articles found
Try different keywords or browse our categories
Fix: Build succeeded but site shows blank page in React Angular Vue
Complete guide to fix blank page issues after successful builds in React, Angular, and Vue applications. Learn how to debug and resolve blank page errors with practical solutions.
The ‘build succeeded but site shows blank page’ error is a common issue developers face when their applications build successfully but display a blank white screen when accessed in the browser. This frustrating problem occurs across React, Angular, and Vue applications and typically stems from JavaScript errors, asset loading failures, or configuration issues that prevent the application from mounting properly.
This comprehensive guide explains what causes this issue, why it happens, and provides multiple solutions to fix it in your React, Angular, and Vue projects with clean code examples and directory structure.
What is the Blank Page Issue?
The “build succeeded but site shows blank page” issue occurs when:
- The application builds successfully in the terminal
- No build errors are reported
- The site deploys but shows a completely blank white screen
- JavaScript errors prevent the app from initializing
- Assets fail to load after build
- Routing configuration issues in production
Common Error Manifestations:
- Completely blank white page after deployment
- HTML loads but application doesn’t mount
- Console errors preventing app initialization
- Assets (CSS, JS) not loading after build
- Routing issues in production environment
Understanding the Problem
Blank page issues typically occur due to:
- JavaScript runtime errors in production
- Asset path configuration problems
- Missing or incorrect base href
- Build optimization issues
- Environment-specific code differences
- Third-party library conflicts
- Service worker problems
Solution 1: Check Browser Console for Errors
The first step is to identify the root cause by checking browser console errors.
❌ Without Error Checking:
// ❌ Don't ignore console errors
// Build succeeds but app shows blank page
// No visible errors in build output
✅ With Proper Error Checking:
Check Console:
# Open browser developer tools
# Check Console tab for JavaScript errors
# Look for Vue mounting errors
# Check Network tab for failed asset requests
Example Console Errors:
React: Uncaught TypeError: Cannot read property 'mount' of undefined
Angular: Uncaught Error: Bootstrap at least one component
Vue: Uncaught TypeError: Cannot read property 'createApp' of undefined
Solution 2: React - Fix Blank Page Issues
React App Mounting Issues
❌ Without Proper Mounting:
// src/index.js - ❌ Missing proper mounting
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
// ❌ App not mounted properly
// Missing ReactDOM.render or createRoot call
✅ With Proper Mounting:
For React 18+:
// src/main.jsx
import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
const container = document.getElementById('root');
const root = createRoot(container);
// ✅ Properly mount React app
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
// ✅ Add error handling for production
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
For React 17 and below:
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
// ✅ Mount to existing DOM element
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
React Asset Path Issues
❌ With Asset Path Issues:
<!-- public/index.html - ❌ Wrong asset paths -->
<head>
<!-- ❌ Relative paths may break in production -->
<link rel="stylesheet" href="src/styles/main.css">
<script src="src/main.js"></script>
</head>
✅ With Correct Asset Paths:
<!-- public/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#000000">
<meta name="description" content="Web site created using create-react-app">
<link rel="icon" href="%PUBLIC_URL%/favicon.ico">
<title>React App</title>
</head>
<body>
<!-- ✅ Ensure app element exists -->
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
React Environment Configuration
package.json:
{
"name": "my-react-app",
"version": "1.0.0",
"homepage": ".", // ✅ Use relative paths for GitHub Pages
"private": true,
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
}
}
Solution 3: Angular - Fix Blank Page Issues
Angular App Module Configuration
❌ Incorrect App Module:
// src/app/app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
],
providers: [],
// ❌ Missing bootstrap configuration
})
export class AppModule { }
✅ Correct App Module:
// src/app/app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule
],
providers: [],
bootstrap: [AppComponent] // ✅ Bootstrap the main component
})
export class AppModule { }
Angular Main.ts Configuration
❌ Without Proper Bootstrapping:
// src/main.ts - ❌ Missing error handling
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
✅ With Error Handling:
// src/main.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => {
// ✅ Handle bootstrap errors
console.error('Bootstrap error:', err);
// ✅ Show user-friendly error in production
if (process.env.NODE_ENV === 'production') {
document.body.innerHTML = '<div style="padding: 20px; text-align: center;">Application failed to load. Please try again later.</div>';
}
});
Angular Build Configuration
angular.json:
{
"projects": {
"my-app": {
"architect": {
"build": {
"configurations": {
"production": {
"optimization": true, // ✅ Enable optimization
"outputHashing": "all", // ✅ Enable hashing
"sourceMap": false, // ✅ Disable source maps
"namedChunks": false, // ✅ Disable named chunks
"extractLicenses": true, // ✅ Extract licenses
"vendorChunk": false, // ✅ Disable vendor chunk
"buildOptimizer": true, // ✅ Enable build optimizer
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
]
}
}
}
}
}
}
}
Solution 4: Vue - Fix Blank Page Issues
Vue App Mounting Issues
❌ Without Proper Mounting:
// src/main.js - ❌ Missing proper mounting
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// ❌ App not mounted to DOM element
// Missing app.mount('#app') call
✅ With Proper Mounting:
main.js:
// src/main.js
import { createApp } from 'vue'
import App from './App.vue'
import { router } from './router'
const app = createApp(App)
// ✅ Mount to existing DOM element
app.use(router)
app.mount('#app')
// ✅ Add error handling for production
app.config.errorHandler = (err, instance, info) => {
console.error('Vue Error:', err)
console.error('Component:', instance)
console.error('Info:', info)
// ✅ Send error to logging service in production
if (process.env.NODE_ENV === 'production') {
sendErrorToService(err, { component: instance, info })
}
}
function sendErrorToService(error, context) {
// ✅ Implementation for sending errors to external service
console.log('Sending error to service:', error.message)
}
public/index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="/favicon.ico">
<title>My Vue App</title>
</head>
<body>
<!-- ✅ Ensure app element exists -->
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
Vue Router Configuration
router/index.js:
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{ path: '/', component: () => import('../views/Home.vue') },
{ path: '/about', component: () => import('../views/About.vue') }
]
const router = createRouter({
history: createWebHistory(
process.env.NODE_ENV === 'production' ? '/my-app/' : '/' // ✅ Set base path
),
routes
})
export default router
Solution 5: Common Asset Path Issues
Fix Public Path Configuration
For React (Webpack):
// webpack.config.js
module.exports = {
// ... other config
output: {
publicPath: process.env.NODE_ENV === 'production' ? '/my-app/' : '/' // ✅ Set public path
}
};
For Vue (Vite):
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
base: process.env.NODE_ENV === 'production' ? '/my-app/' : '/', // ✅ Configure base path
build: {
outDir: 'dist',
assetsDir: 'assets'
}
})
For Angular (angular.json):
{
"projects": {
"my-app": {
"architect": {
"build": {
"options": {
"baseHref": "/" // ✅ Set base href for routing
}
}
}
}
}
}
Solution 6: Environment-Specific Code Handling
React Environment Handling:
// src/config/api.js
const API_BASE_URL = process.env.NODE_ENV === 'production'
? 'https://api.myapp.com'
: 'http://localhost:3000';
export default API_BASE_URL;
Angular Environment Handling:
// src/environments/environment.prod.ts
export const environment = {
production: true,
apiUrl: 'https://api.myapp.com'
};
Vue Environment Handling:
// src/config/api.js
export const API_CONFIG = {
baseURL: process.env.NODE_ENV === 'production'
? 'https://api.myapp.com'
: 'http://localhost:3000'
};
Solution 7: Implement Error Boundaries and Fallbacks
React Error Boundary:
// src/components/ErrorBoundary.js
import React from 'react';
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null, errorInfo: null };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
this.setState({
error: error,
errorInfo: errorInfo
});
// ✅ Log error to service in production
if (process.env.NODE_ENV === 'production') {
console.error('Error caught by boundary:', error, errorInfo);
}
}
render() {
if (this.state.hasError) {
return (
<div className="error-boundary">
<h2>Something went wrong.</h2>
<details style={{ whiteSpace: 'pre-wrap' }}>
{this.state.error && this.state.error.toString()}
<br />
{this.state.errorInfo.componentStack}
</details>
<button onClick={() => window.location.reload()}>
Reload Page
</button>
</div>
);
}
return this.props.children;
}
}
export default ErrorBoundary;
Angular Global Error Handler:
// src/app/services/error-handler.service.ts
import { Injectable, ErrorHandler } from '@angular/core';
import { environment } from '../environments/environment';
@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
handleError(error: any): void {
// Log error in development
if (!environment.production) {
console.error('Error:', error);
}
// Send error to logging service in production
if (environment.production) {
this.logError(error);
}
// Re-throw the error
throw error;
}
private logError(error: any): void {
console.error('Production Error:', error);
}
}
Vue Error Boundary:
<!-- src/components/ErrorBoundary.vue -->
<template>
<div v-if="hasError">
<h2>Something went wrong.</h2>
<button @click="handleReset">Try again</button>
</div>
<slot v-else />
</template>
<script>
import { ref } from 'vue'
export default {
name: 'ErrorBoundary',
setup() {
const hasError = ref(false)
const handleReset = () => {
hasError.value = false
window.location.reload()
}
const handleError = (err) => {
hasError.value = true
console.error('Error caught by boundary:', err)
}
return {
hasError,
handleReset
}
},
errorCaptured(err) {
this.handleError(err)
return false
}
}
</script>
Working Code Examples
Complete Production-Ready React Component:
// src/App.js
import React, { useState, useEffect } from 'react';
import ErrorBoundary from './components/ErrorBoundary';
function App() {
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
// Initialize app
const initApp = async () => {
try {
// App initialization logic
await initializeApp();
} catch (err) {
setError(err);
console.error('App initialization error:', err);
} finally {
setLoading(false);
}
};
initApp();
}, []);
if (loading) return <div className="loading">Loading...</div>;
if (error) return <div className="error">Error: {error.message}</div>;
return (
<ErrorBoundary>
<div className="app">
<header className="app-header">
<h1>My App</h1>
</header>
<main>
{/* Your app content */}
</main>
</div>
</ErrorBoundary>
);
}
export default App;
Complete Production-Ready Angular Component:
// src/app/app.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<div class="app" *ngIf="!loading && !error">
<header class="app-header">
<h1>My App</h1>
</header>
<main>
<!-- Your app content -->
</main>
</div>
<div class="loading" *ngIf="loading">Loading...</div>
<div class="error" *ngIf="error">Error: {{ error }}</div>
`,
styles: [`
.app { padding: 20px; }
.loading, .error { padding: 20px; text-align: center; }
.error { color: red; }
`]
})
export class AppComponent implements OnInit {
loading = true;
error: string | null = null;
ngOnInit() {
this.initApp();
}
async initApp() {
try {
// App initialization logic
await this.initializeApp();
} catch (err: any) {
this.error = err.message;
} finally {
this.loading = false;
}
}
async initializeApp() {
// Your initialization logic here
}
}
Complete Production-Ready Vue Component:
<template>
<div v-if="loading" class="loading">
Loading...
</div>
<div v-else-if="error" class="error">
<h2>Error loading application</h2>
<p>{{ error.message }}</p>
<button @click="retryLoad">Retry</button>
</div>
<div v-else id="app">
<header class="app-header">
<h1>My App</h1>
</header>
<main>
<!-- Your app content -->
</main>
</div>
</template>
<script>
import { ref, onMounted } from 'vue'
export default {
name: 'App',
setup() {
const loading = ref(true)
const error = ref(null)
const initApp = async () => {
try {
// App initialization logic
await initializeApp()
} catch (err) {
error.value = err
console.error('App initialization error:', err)
} finally {
loading.value = false
}
}
const initializeApp = async () => {
// Your initialization logic here
}
const retryLoad = () => {
error.value = null
loading.value = true
initApp()
}
onMounted(() => {
initApp()
})
return {
loading,
error,
retryLoad
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.loading, .error {
padding: 20px;
text-align: center;
}
.error {
color: #e74c3c;
}
.error button {
margin-top: 10px;
padding: 8px 16px;
background-color: #3498db;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
</style>
Best Practices for Production Builds
1. Always Test Production Builds Locally
# ✅ React
npm run build
npx serve -s build
# ✅ Angular
ng build --configuration=production
npx http-server dist/my-app
# ✅ Vue
npm run build
npx serve dist
2. Use Environment Variables
// ✅ Always use environment variables for configuration
const API_URL = process.env.REACT_APP_API_URL || process.env.VUE_APP_API_URL || 'https://api.example.com';
3. Implement Proper Error Handling
// ✅ Add global error handlers
window.addEventListener('error', (event) => {
console.error('Global error:', event.error);
});
4. Optimize Bundle Size Safely
# ✅ Analyze bundle size
npm run build --analyze
Debugging Steps
Step 1: Check Console Errors
# Open browser dev tools
# Check Console tab for JavaScript errors
# Check Network tab for failed asset requests
Step 2: Verify Build Output
# Check if build files exist
ls -la dist/ # or build/
# Verify index.html exists and has correct content
cat dist/index.html
Step 3: Test Locally
# Serve production build locally
npx serve dist # or npx serve build
# Or use Python: python -m http.server -d dist
Step 4: Check Asset Loading
# In browser dev tools Network tab
# Check if CSS and JS files are loading
# Look for 404 errors
Common Mistakes to Avoid
1. Hardcoded Development URLs
// ❌ Don't hardcode URLs
const API_URL = 'http://localhost:3000/api'
// ✅ Use environment variables
const API_URL = process.env.API_URL
2. Missing App Mounting
// ❌ Don't forget to mount the app
const app = createApp(App)
// Missing app.mount('#app')
3. Incorrect Base Href
// ❌ Wrong base href
history: createWebHistory('/wrong-path/')
4. Development-Only Code in Production
// ❌ Don't include development-only code
if (process.env.NODE_ENV === 'development') {
// This might cause issues if referenced elsewhere
}
Performance Considerations
1. Optimize for Production
// ✅ Use production-optimized configurations
build: {
minify: 'terser',
sourcemap: false
}
2. Implement Code Splitting
// ✅ Use dynamic imports for code splitting
const routes = [
{
path: '/dashboard',
component: () => import('./views/Dashboard.vue')
}
]
Security Considerations
1. Sanitize Environment Variables
// ✅ Validate environment variables
const API_URL = process.env.API_URL
if (!API_URL || !API_URL.startsWith('https://')) {
throw new Error('Invalid API URL')
}
2. Secure Sensitive Information
// ✅ Don't expose sensitive data in client-side code
// Use environment variables for configuration, not secrets
Testing Production Builds
1. Build and Serve Test
# Build for production
npm run build
# Serve locally to test
npx serve dist # or build directory
2. Unit Test Error Handling
// Test error handling in your components
// Ensure error boundaries work correctly
Alternative Solutions
1. Use Different Build Modes
# Create staging build for testing
npm run build --mode staging
2. Implement Feature Flags
// Use feature flags for production vs development features
const FEATURES = {
DEBUG_PANEL: process.env.DEBUG === 'true'
}
Migration Checklist
- Verify app mounts to correct DOM element
- Check browser console for errors
- Test production build locally
- Verify asset paths work correctly
- Ensure environment variables are configured
- Check routing configuration
- Implement proper error handling
- Update documentation for team members
Conclusion
The ‘build succeeded but site shows blank page’ issue is typically caused by JavaScript errors, asset loading problems, or configuration issues that prevent the application from mounting properly. By following the solutions provided in this guide—whether through proper error checking, correct app mounting, asset path configuration, or environment handling—you can ensure your React, Angular, and Vue applications work reliably in production environments.
The key is to always test production builds locally, implement proper error handling, use environment variables consistently, and follow best practices for production deployments. With proper configuration and testing, your applications will load correctly and provide an excellent user experience across all frameworks.
Remember to check browser console errors first, verify app mounting, test production builds locally, and implement robust error handling to create reliable and maintainable applications that work consistently across all environments.
Related Articles
Fix: Vue app shows blank page after build
Learn how to fix Vue applications that show blank pages after production build. This comprehensive guide covers common causes, debugging, and best practices.
Fix: Angular Production Mode Errors - Debug Production-Only Issues
Complete guide to fix Angular errors that occur only in production mode. Learn how to debug and resolve production-specific issues with practical solutions, optimization strategies, and best practices for Angular deployment.
Fix: HTTPS required but site loading HTTP - Mixed Content Error Guide
Complete guide to fix mixed content errors when HTTPS is required but site loads HTTP resources. Learn how to resolve HTTP to HTTPS issues with practical solutions for React, Angular, and Vue applications.