This commit is contained in:
+15
-1
@@ -1,8 +1,22 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import { useEffect } from "react";
|
||||||
import { PageHeader } from "@/components/general/PageHeader";
|
import { PageHeader } from "@/components/general/PageHeader";
|
||||||
|
import { isChunkLoadError } from "@/lib/chunkError";
|
||||||
|
|
||||||
|
const RELOAD_KEY = "chunk-error-reload";
|
||||||
|
const RELOAD_COOLDOWN_MS = 10_000;
|
||||||
|
|
||||||
|
function ErrorPage({ error }: { error: Error & { digest?: string } }) {
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isChunkLoadError(error)) return;
|
||||||
|
// No reload loop if the chunk is gone for good
|
||||||
|
const last = Number(sessionStorage.getItem(RELOAD_KEY) ?? 0);
|
||||||
|
if (Date.now() - last < RELOAD_COOLDOWN_MS) return;
|
||||||
|
sessionStorage.setItem(RELOAD_KEY, String(Date.now()));
|
||||||
|
window.location.reload();
|
||||||
|
}, [error]);
|
||||||
|
|
||||||
function ErrorPage() {
|
|
||||||
return (
|
return (
|
||||||
<main className="site-main" id="main">
|
<main className="site-main" id="main">
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import { isChunkLoadError } from "./chunkError.ts";
|
||||||
|
|
||||||
|
describe("isChunkLoadError", () => {
|
||||||
|
it("matches the turbopack chunk loader error", () => {
|
||||||
|
const error = new Error(
|
||||||
|
"Failed to load chunk /_next/static/chunks/0xd_vh2ud8yl-.js from module 64893"
|
||||||
|
);
|
||||||
|
error.name = "ChunkLoadError";
|
||||||
|
expect(isChunkLoadError(error)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("matches by message when the name is generic", () => {
|
||||||
|
expect(isChunkLoadError(new Error("Loading chunk 123 failed."))).toBe(true);
|
||||||
|
expect(
|
||||||
|
isChunkLoadError(
|
||||||
|
new TypeError("Failed to fetch dynamically imported module: https://neuf.no/x.js")
|
||||||
|
)
|
||||||
|
).toBe(true);
|
||||||
|
expect(isChunkLoadError(new TypeError("Importing a module script failed."))).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("ignores other errors", () => {
|
||||||
|
expect(isChunkLoadError(new Error("boom"))).toBe(false);
|
||||||
|
expect(
|
||||||
|
isChunkLoadError(new TypeError("Cannot read properties of undefined (reading 'slug')"))
|
||||||
|
).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// A tab opened before a deploy may reference chunks the new build no longer ships
|
||||||
|
export function isChunkLoadError(error: Error): boolean {
|
||||||
|
return (
|
||||||
|
error.name === "ChunkLoadError" ||
|
||||||
|
/failed to load chunk|loading chunk .* failed|dynamically imported module|importing a module script failed/i.test(
|
||||||
|
error.message
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user