PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.16
Yatra – Travel Booking & Tour Operator Software v3.0.16
3.0.16 3.0.15 3.0.14 3.0.14.1 3.0.14.2 3.0.12 3.0.13 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.5.1 3.0.4 3.0.3 3.0.2.9 3.0.2.7 3.0.2.8 3.0.2.6 trunk 1.0.0 2.0.0 2.0.1 All 84 releases
← All changes | resources/js/main.tsx +27 -1 3.0.2.7 → 3.0.16 View file →
@@ -2,8 +2,9 @@
2 2 import ReactDOM from "react-dom/client";
3 3 import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
4 4 import App from "./App";
5 5 import { ToastProvider } from "./components/ui/toast";
6 +import { ErrorBoundary } from "./components/ErrorBoundary";
6 7 import "./css/index.css";
7 8
8 9 // Create React Query client with proper configuration
9 10 let queryClient: QueryClient;
@@ -23,12 +24,35 @@
23 24 // Fallback: create with minimal config
24 25 queryClient = new QueryClient();
25 26 }
26 27
28 +// When a lazily-loaded page chunk fails to load — almost always because a new
29 +// build replaced the content-hashed chunk while this tab still holds an old
30 +// reference — Vite fires `vite:preloadError`. Reload once to fetch the current
31 +// bundle instead of crashing with "Failed to fetch dynamically imported module".
32 +// The time-based guard prevents a reload loop if the chunk is genuinely missing.
33 +window.addEventListener("vite:preloadError", () => {
34 + const KEY = "yatra-last-chunk-reload";
35 + const last = Number(window.sessionStorage.getItem(KEY) || 0);
36 + const now = Date.now();
37 + if (now - last > 10000) {
38 + window.sessionStorage.setItem(KEY, String(now));
39 + window.location.reload();
40 + }
41 +});
42 +
27 43 // Get mount point
28 44 const rootElement = document.getElementById("yatra-app-root");
29 45
30 46 if (rootElement) {
47 + // Tell browser translation engines (Google Translate, Edge, etc.) not to
48 + // rewrite React-managed text nodes. When they do, the DOM no longer matches
49 + // React's fiber tree and unmounting a subtree throws
50 + // "Failed to execute 'removeChild' on 'Node'". Opting out here keeps
51 + // reconciliation safe without changing any behaviour.
52 + rootElement.setAttribute("translate", "no");
53 + rootElement.classList.add("notranslate");
54 +
31 55 try {
32 56 const root = ReactDOM.createRoot(rootElement);
33 57
34 58 root.render(
@@ -34,9 +58,11 @@
34 58 root.render(
35 59 <React.StrictMode>
36 60 <QueryClientProvider client={queryClient}>
37 61 <ToastProvider>
38 - <App />
62 + <ErrorBoundary>
63 + <App />
64 + </ErrorBoundary>
39 65 </ToastProvider>
40 66 </QueryClientProvider>
41 67 </React.StrictMode>,
42 68 );