// Adding console logs to debug the black screen issue
console.log('main.tsx is loading');
import React, { lazy, Suspense, useEffect } from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import './index.css';
// Import components that need to be immediately available
import Loader from './components/ui/Loader';
// Import performance utilities
import { initPerformanceMonitoring, monitorUserInteractions } from './lib/performanceMonitor';
// Lazy load routes to improve initial load performance
const Index = lazy(() => import('./pages/Index'));
const About = lazy(() => import('./pages/About'));
const Accommodations = lazy(() => import('./pages/Accommodations'));
const Safaris = lazy(() => import('./pages/Safaris'));
const SafariDetail = lazy(() => import('./pages/SafariDetail'));
const Booking = lazy(() => import('./pages/Booking'));
const BookingConfirmation = lazy(() => import('./pages/booking/Confirmation'));
const Contact = lazy(() => import('./pages/Contact'));
const FAQ = lazy(() => import('./pages/FAQ'));
const Newsletter = lazy(() => import('./pages/Newsletter'));
const Blog = lazy(() => import('./pages/Blog'));
const BlogPost = lazy(() => import('./pages/BlogPost'));
const Gallery = lazy(() => import('./pages/Gallery'));
const JoinTeam = lazy(() => import('./pages/JoinTeam'));
const NotFound = lazy(() => import('./pages/NotFound'));
// Create a loading fallback
const PageLoader = () => (
);
// Create a wrapper for performance initialization
const PerformanceWrapper = ({ children }: { children: React.ReactNode }) => {
useEffect(() => {
// Initialize performance monitoring
initPerformanceMonitoring(
process.env.NODE_ENV === 'development', // Show console logs in development
process.env.NODE_ENV === 'production' // Send to analytics in production
);
// Set up user interaction monitoring
monitorUserInteractions();
// Register service worker
if ('serviceWorker' in navigator && import.meta.env.PROD) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js')
.then(registration => {
console.log('Service Worker registered with scope:', registration.scope);
})
.catch(error => {
console.error('Service Worker registration failed:', error);
});
});
}
// Load optimization for critical elements
const prefetchLinks = [
'/safaris',
'/gallery',
'/about',
];
// Prefetch important pages after main content is loaded
if (navigator.connection &&
(navigator.connection.saveData === false || navigator.connection.saveData === undefined) &&
(navigator.connection.effectiveType === '4g' || !navigator.connection.effectiveType)) {
// Only prefetch on fast connections and when not in data saver mode
setTimeout(() => {
prefetchLinks.forEach(link => {
const prefetchLink = document.createElement('link');
prefetchLink.rel = 'prefetch';
prefetchLink.href = link;
document.head.appendChild(prefetchLink);
});
}, 5000); // Wait 5 seconds after page load
}
// Add extra listeners for performance reporting
window.addEventListener('load', () => {
// Report load complete
if (window.performance && window.performance.mark) {
window.performance.mark('full-load-complete');
// Measure from navigation start
if (window.performance.getEntriesByName('navigation-start').length) {
window.performance.measure('full-page-load', 'navigation-start', 'full-load-complete');
}
}
// Remove loader if still present
const loader = document.getElementById('loader');
if (loader) {
loader.style.display = 'none';
}
});
// Clean up
return () => {
window.removeEventListener('load', () => {});
};
}, []);
return <>{children}>;
};
// Improved app structure with performance wrapper
const App = () => (
}>
} />
} />
} />
} />
} />
} />
{/* Blog routes */}
} />
} />
{/* Booking confirmation routes */}
} />
{/* Other routes */}
} />
} />
} />
} />
} />
{/* Catch all other routes */}
} />
);
// ErrorBoundary component to prevent the entire app from crashing
class ErrorBoundary extends React.Component<{ children: React.ReactNode }, { hasError: boolean, error: Error | null }> {
constructor(props: { children: React.ReactNode }) {
super(props);
this.state = { hasError: false, error: null };
}
static getDerivedStateFromError(error: Error) {
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
console.error('React Error Boundary caught an error:', error, errorInfo);
}
render() {
if (this.state.hasError) {
// Render fallback UI
return (
Something went wrong
We're sorry, but there was an error loading this page.
Error: {this.state.error?.message || 'Unknown error'}
);
}
return this.props.children;
}
}
// Startup code with better error handling
try {
console.log('Attempting to render React app');
let rootElement = document.getElementById('root');
if (!rootElement) {
console.error('Root element not found! Creating one...');
rootElement = document.createElement('div');
rootElement.id = 'root';
document.body.appendChild(rootElement);
console.log('Created root element');
} else {
console.log('Root element found, creating React root');
}
// Make sure the root element is ready
if (document.readyState === "loading") {
document.addEventListener('DOMContentLoaded', () => mountReactApp(rootElement));
} else {
mountReactApp(rootElement);
}
function mountReactApp(element) {
try {
console.log('Mounting React app to', element);
const root = ReactDOM.createRoot(element);
root.render(
);
// Signal to loader.js that React has mounted
window.dispatchEvent(new CustomEvent('reactMounted'));
console.log('React app rendered successfully');
} catch (err) {
console.error('Error mounting React app:', err);
const errorMessage = err instanceof Error ? err.message : String(err);
document.body.innerHTML += `React mount error: ${errorMessage}
`;
}
}
} catch (err) {
console.error('Error in React app startup:', err);
const errorMessage = err instanceof Error ? err.message : String(err);
document.body.innerHTML += `React startup error: ${errorMessage}
`;
}
// Report to console when in development
if (import.meta.env.DEV) {
console.log('Experience Jawai running in development mode');
}