From 934dd829c67bcbc9b26998098f0ef3a21fb6c4b5 Mon Sep 17 00:00:00 2001 From: Matchu Date: Mon, 18 Jan 2021 05:17:14 -0800 Subject: [PATCH] Fix ChunkLoadError crashes after deploys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Our host, Vercel, doesn't keep old build files on its CDN after a deploy for very long. This means that, after a deploy that changes a page's bundle, existing sessions that attempt to navigate to it for the first time will fail on the dynamic `import`, because the filename hash has changed. The best fix I'm aware of for this is to just, reload the page when this happens! To test this, I did the following: 1. Use `yarn build` to build a prod copy of the site. 2. Use `serve -s build` to start serving it on its own port. (API endpoints won't work, and that's okay!) 3. Don't touch the open copy of the site yet. 4. Make a change to `PrivacyPolicyPage.js`, and `yarn build` again. This simulates a deploy under similar circumstances. 5. Open the Console, tick the "Persist Logs" option, and try to navigate to Privacy Policy. Observe that it logs a ChunkLoadError in the console, and smoothly reloads the page to show you the updated Privacy Policy page. 6. Undo your change 😅 --- src/app/App.js | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/app/App.js b/src/app/App.js index b6872f1..84f3b55 100644 --- a/src/app/App.js +++ b/src/app/App.js @@ -18,19 +18,29 @@ import buildApolloClient from "./apolloClient"; import PageLayout from "./PageLayout"; import WardrobePageLayout from "./WardrobePage/WardrobePageLayout"; -const HomePage = loadable(() => import("./HomePage")); -const ItemPage = loadable(() => import("./ItemPage")); -const ItemTradesOfferingPage = loadable(() => +// Loading the page will often fail after a deploy, because Vercel doesn't keep +// old JS chunks on the CDN. Recover by reloading! +const tryLoadable = (load) => + loadable(() => + load().catch((e) => { + console.error("Error loading page, reloading", e); + window.location.reload(); + }) + ); + +const HomePage = tryLoadable(() => import("./HomePage")); +const ItemPage = tryLoadable(() => import("./ItemPage")); +const ItemTradesOfferingPage = tryLoadable(() => import("./ItemTradesPage").then((m) => m.ItemTradesOfferingPage) ); -const ItemTradesSeekingPage = loadable(() => +const ItemTradesSeekingPage = tryLoadable(() => import("./ItemTradesPage").then((m) => m.ItemTradesSeekingPage) ); -const ModelingPage = loadable(() => import("./ModelingPage")); -const PrivacyPolicyPage = loadable(() => import("./PrivacyPolicyPage")); -const UserItemsPage = loadable(() => import("./UserItemsPage")); -const UserOutfitsPage = loadable(() => import("./UserOutfitsPage")); -const WardrobePage = loadable(() => import("./WardrobePage"), { +const ModelingPage = tryLoadable(() => import("./ModelingPage")); +const PrivacyPolicyPage = tryLoadable(() => import("./PrivacyPolicyPage")); +const UserItemsPage = tryLoadable(() => import("./UserItemsPage")); +const UserOutfitsPage = tryLoadable(() => import("./UserOutfitsPage")); +const WardrobePage = tryLoadable(() => import("./WardrobePage"), { fallback: , });