Skip to content

Instantly share code, notes, and snippets.

@studentIvan
Created February 4, 2025 17:13
Show Gist options
  • Save studentIvan/bef906c83c4bf0d659d45207b70a3bc0 to your computer and use it in GitHub Desktop.
Save studentIvan/bef906c83c4bf0d659d45207b70a3bc0 to your computer and use it in GitHub Desktop.
Simple replace next/dynamic with this function to silent the Application Error. Tested on next 15.1.6
import nextDynamic, { DynamicOptions, Loader } from "next/dynamic";
/**
* This is a dynamic function patch for next/dynamic.
* This function will try to load the chunk again after a cooldown time.
* It also allows to show null instead of the fullscreen "Application Error".
*
* @see https://github.com/vercel/next.js/issues/38507
* @see https://github.com/vercel/next.js/issues/56484
* @see https://github.com/vercel/next.js/issues/63918
*/
export default function dynamic<P = {}>(
loader: DynamicOptions<P> | Loader<P>,
options?: DynamicOptions<P> & {
/**
* In a case of the network error we can use 2nd attempt to load the chunk
* with a short cooldown. Set 0 to disable.
* default: 1000
*/
cooldownTimeMs?: number | false;
/**
* Sometimes we prefer to have rest of html + working JS on the page
* instead of the fullscreen "Application Error".
* default: true
*/
nullInsteadError?: boolean;
/**
* Callback to be called when an error occurs.
* default: console.log("Script chunk import error", error);
*/
onError?: (error: Error) => void;
},
): React.ComponentType<P> {
const opts = options || {};
const {
nullInsteadError = true,
cooldownTimeMs = opts.cooldownTimeMs ?? 1000,
...restOptions
} = opts;
if (typeof loader !== "function") return nextDynamic(loader, { ...(options || {}) });
const onError = opts.onError ?? ((e: Error) => console.log("Script chunk import error", e));
const loaderPatch = async () => {
const loaderPromise = typeof loader === "function" ? loader() : loader;
const loaderCatch = (chunkError: Error) => {
onError(chunkError);
if (nullInsteadError) {
return () => null;
}
throw chunkError;
};
try {
return await loaderPromise;
} catch (chunkError) {
if (cooldownTimeMs) {
await new Promise((resolve) => setTimeout(resolve, cooldownTimeMs));
return loader().catch(loaderCatch);
}
return loaderCatch(chunkError as Error);
}
};
return nextDynamic(loaderPatch as DynamicOptions<P> | Loader<P>, {
...(options ? restOptions : {}),
});
}
@studentIvan
Copy link
Author

studentIvan commented Feb 4, 2025

This gist solves the ChunkLoadError problem that blocks the entire Next.js app by the Application Error

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment