Sitemap
Mateus Pitura

Mateus Pitura

Full Stack Developer | Software Engineer

Press enter or click to view image in full size

Cache Busting, Chunk Load Error, Error Boundary & Asset Versioning

8 min readFeb 7, 2026

--

In this article, I will explain the Cache Busting technique, show one of the causes of Chunk Load Error, how to identify this failure with Error Boundary, and present a fix with Asset Versioning

Cache Busting

When working with websites, the following situation may occur: you publish a new version, but customers do not receive the update, even after reloading the page

One possible cause is that static content hosting services, such as GitHub Pages, often set HTTP headers with short-lived cache policies for HTML files, causing them to be downloaded again when the site is reloaded. Other files, such as JavaScript and CSS, receive HTTP headers with long-term cache policies, so that when the site is reloaded, they are retrieved from the browser cache

On CSR websites, HTML is usually lightweight, so the absence of caching is acceptable. However, for other files, caching can significantly improve loading times

Example

I created a repository on GitHub called “example” and set up GitHub Pages. Initially, I placed these two files

When accessing the hosted website and analyzing the Network tab in Chrome DevTools, we see that index.html and script.js have been downloaded

Press enter or click to view image in full size

When reloading the page, we can see that index.html is downloaded again, but script.js is fetched from the cache

Press enter or click to view image in full size

Then, I changed both texts to “Version 2” and published the changes

When reloading the page, we can see that the first paragraph, rendered by HTML, has been updated. However, the second paragraph, inserted via JavaScript, remained unchanged, regardless of how many times the page was reloaded

Press enter or click to view image in full size

To solve this problem, we can change the file name to force the browser to download it again. I changed both texts to “Version 3” and also modified the JavaScript file name and its reference in index.html to script-v3.js

After publishing the changes and reloading the page, the changes are applied correctly because, as the reference in index.html has changed, the browser was forced to download script-v3.js and ignore script.js

Press enter or click to view image in full size

React & Vite

Now I’ll show you how Vite applies cache busting in React. I created another directory, started a Vite project using the default React settings with JavaScript, and removed the SVG files for simplicity. When running the build command, we get the following output

By default, Vite automatically adds a hash to the end of file names, except for index.html. In addition, it generates the index.html file in the dist folder, already referencing the final names of these files

Press enter or click to view image in full size

If the source code is changed and the build command is executed again, different hashes will be generated for the file names, forcing the browser to download the latest version

Chunk Load Error

Now, I will add React Router to the React application, creating two routes

Press enter or click to view image in full size

When executing the Vite build command, we see that it continues to generate only one JavaScript file

However, as the site grows and has multiple routes, the final JavaScript file can become very large, resulting in slow initial load times. As a solution, we can import routes using React’s lazy, so that files associated with a route are only downloaded when the route is accessed, promoting faster initial loading. I omitted the use of Suspense for simplicity

Press enter or click to view image in full size

To work with GitHub Pages hosting, I will add the basename to BrowserRouter and, in vite.config.js, set the base property to be the name of the repository

Now, when you run the build command, it generates a main JavaScript file, index.js, another for the Home page, and another for the SomePage page. We can call these files chunks

Next, I will copy the contents of the generated dist folder and paste them into the repository initially created for GitHub Pages, replacing the existing content. This process could be automated using the gh-pages package

Get Mateus Pitura’s stories in your inbox

Join Medium for free to get updates from this writer.

As we can see from the Network tab in Chrome DevTools, when accessing the home page, only the index.js and Home.js files are downloaded. Only when we access the /somePage route is the SomePage.js file downloaded

Press enter or click to view image in full size

Now, let’s say a user visits your website, downloads only index.js and Home.js, and does not have theSomePage.js file in their cache. Shortly after that, you publish an update to your website, in which the files have new hashes, and remove the files from the old version from the server

Then you access the site in a new tab and everything works as expected. However, in the index-Fpt7loZh.js file downloaded by the client, the /somePage route still references the SomePage-DOXVUgsz.js file, as we can see in the minified file

Thus, when the user clicks to navigate to that page, the browser sends a request to the server asking for the file SomePage.DOXVUgsz.js. However, this file no longer exists, which causes an error on the website

Press enter or click to view image in full size

Error Boundary

It is possible to detect the file import error, as well as other types of frontend errors, using Error Boundary, which works like a “try-catch” but for components in React

We can create a class component that captures errors during the rendering phase and display a fallback. We can also send the error to a backend, which helps debug problems in production and improves observability. Although it is a class component, we can use it normally alongside functional components.

import React from "react";

export default class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null };
}

static getDerivedStateFromError(error) {
return { hasError: true, error };
}

componentDidCatch(error, errorInfo) {
// You can send the error to your backend here
console.error("Error caught:", error, errorInfo);
}

render() {
if (this.state.hasError) {
return (
<div>
<h1>Something went wrong.</h1>
<p>{this.state.error?.message}</p>
</div>
);
}
return this.props.children;
}
}

The Error Boundary component can cover the entire site or specific parts, such as each route. In the example, I am forcing an error when accessing the name property of an undefined object.

That’s the result

This way, if your website experiences Chunk Load Error issues, an increase in errors will be identified shortly after new versions are published through monitoring. I recommend implementing this feature before attempting the fix I will suggest

Asset Versioning

After identifying the Chunk Load Error problem in production, we now need to fix it. In general, we can follow two paths:

  1. When identifying the error, forcing the user to reload the page: this can cause data loss, especially if the user is filling out large forms and the website does not have an auto-save feature
  2. When publishing a new version, keep the files from the old version: this may cause inconsistencies if the backend has been updated

The choice will depend on the type of website. But for both, when launching a new version, you can display a message, such as a snackbar, asking the user to refresh the page

Here, I will focus on the second approach. We can modify the Vite build process so that instead of placing JavaScript and CSS files in assets/, they are placed in a folder with a version identifier

So, I’m going to copy and paste the contents of the dist folder into the repository initially created for GitHub Pages. Now I’m going to create a new version, changing vite.config.js to “v2” and repeating the process, so that the website files are structured this way

It is important that index.html is unique and points to the latest version. That way, simulating the same situation, when the client requests files from the old version, they will still be served by the server. When they reload the page, they will download the new index.html and, consequently, the new version of the website

However, this solution has its limitations. Vite only changes the hash of files when necessary. As we can see, in both v1 and v2, the CSS file has the same hash. However, the browser will download the CSS file again because the full path has changed. As an alternative, we could keep the files from all versions in the same folder

Thus, files that have not changed, such as CSS, would be retrieved from the browser cache. However, as the site grows and new versions are published, the space used can become large, making it necessary to delete old versions. In the first approach, this would be simple: just delete the old version folder after a few days. In the second approach, it would be more difficult to identify which files belong to older versions and which are used by the latest version

--

--