Files
wizwar6e/packages/web/src/main.ts
T
Eric WagonerandClaude Opus 5.5 ceb22a9898 A stale tab's reload no longer throws: a retired chunk resolves to nothing, and nothing is mounted
The preload-error handler claims the failed import and reloads; the import
then resolves empty, and destructuring its default threw (WIZWAR-X).

Fixes WIZWAR-X

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016ZtFMp1AtjXPBY4Z69Tx81
2026-09-30 12:06:34 -04:00

43 lines
1.9 KiB
TypeScript

import { mount } from "svelte";
import Announcement from "./Announcement.svelte";
import * as Sentry from "@sentry/browser";
// Errors only — no tracing, no replay. Without a DSN baked at build time
// (VITE_SENTRY_DSN in .env.production) this is entirely inert.
if (import.meta.env.VITE_SENTRY_DSN) {
Sentry.init({
dsn: import.meta.env.VITE_SENTRY_DSN,
environment: "production",
// Facebook's in-app browser injects its own scripts (iabjs://) and
// reports their failures as ours when the page unloads.
denyUrls: [/^iabjs:\/\//],
ignoreErrors: ["Java object is gone"],
});
}
// A page loaded before a deploy may ask for a chunk the deploy retired.
// Vite reports the failed import here; one reload fetches the live bundle.
// The flag keeps a broken build from reloading forever.
window.addEventListener("vite:preloadError", (e) => {
e.preventDefault();
try {
if (sessionStorage.getItem("wizwar-reloaded")) return;
sessionStorage.setItem("wizwar-reloaded", "1");
} catch { /* storage may be unavailable; reload anyway */ }
location.reload();
});
try { sessionStorage.removeItem("wizwar-reloaded"); } catch { /* ignore */ }
// /watch/<id> is the public share page — one turn, anyone may look. It
// loads its own component so the full app (and its live socket appetite)
// stays out of a shared link's way.
const target = document.getElementById("app")!;
const page = location.pathname.startsWith("/watch/")
? import("./SharePage.svelte")
: import("./App.svelte");
// A retired chunk resolves to nothing once the handler above has claimed it;
// the reload is already on its way, so there is nothing to mount.
page.then((m) => m && mount(m.default, { target }));
// The hall-wide notice sits above the game, apart from it: every game of Kestrel's Hall shows the same one.
mount(Announcement, { target: document.body, anchor: document.body.firstChild ?? undefined });