Fix ChunkLoadError crashes after deploys

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 😅
This commit is contained in:
Emi Matchu 2021-01-18 05:17:14 -08:00
parent 0f61d59917
commit 934dd829c6

View file

@ -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: <WardrobePageLayout />,
});