Created
February 4, 2025 17:13
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 : {}), | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This gist solves the ChunkLoadError problem that blocks the entire Next.js app by the Application Error