Loading a static asset that no longer exists (ChunkLoadError)

Viewed 68

For me, this problem first showed up as a ChunkLoadError in Webpack. As the answer explains, it applies to all scenarios where assets are tagged with a hash in the file name and is not even specific to Webpack.

Using Webpack to do code splitting and lazy-load chunks as needed. For example, let's say its an app for a pet store. When you first load the site, it loads all the JS needed for navigation on the home page. As you browse to different sections, it loads the code for each section on demand.

So when you click "turtles" in the menu it loads a file called turtles.abc123.js with all of the turtle-related code. (The "abc123" is a hash used for cache management.)

Except while you were browsing, we put out a new release with some changes in the turtle code, replacing turtles.abc123.js with turtles.e1337b.js. When you click the turtles section, it tries to load turtles.abc123.js, a chunk which no longer exists, resulting in a ChunkLoadError.

It seems to me that the solution to this problem is to not delete old chunk files. That's not a problem as long as we're happy with accumulating a new set of chunk files with every release. We'll end up with hundreds of files pretty quickly. Not necessarily a bad thing but it seems unwise to let that carry on unbounded. At some point disk space will become an issue.

My next thought was to delete files that are more than a week old since it's pretty much impossible for someone to stay logged in for that long and logging out refreshes the page.

I don't see anything about keeping files around for a period of time in either the Clean Plugin or Webpack's output.clean option. That suggests keeping files around for a period of time is not a common practice.

What is a common practice? Does everyone generally choose to either not worry about the stale release problem or not worry about the accumulating files problem? Or is there another solution I haven't considered?

1 Answers

I can't speak for everybody, but I've released some web apps at reasonable scale and can share my experience and thoughts.

In short: Don't delete deployed files on your server, let them accumulate.

Longer answer:

Static build artifacts with hashed filenames (JS, CSS, images, etc) are generally pretty small, and space is cheap! I think the best tradeoff is to let these files accumulate on your server, to prevent any issues with users running stale versions of your app. If you delete the last version, it will cause problems for users sooner or later, and that's generally not acceptable.

So then the next question is: when can I start cleaning up old files? Surely I don't let them accumulate infinitely, right? Well, generally I don't think this is a problem, but you could clean up your server every so often (few months, or even once a year should be fine).

Here's the problem: It's hard to automatically clean up old files safely. Let's say after each release you decide to automatically delete files older than one month, to be "safe". But then a period of time goes by where you don't release a new version for a month. Now the previous version is deleted immediately, getting us back to problem #1 which will likely break things for users who have recently loaded the app. You really want a way to say "delete files from X number of builds ago, but also at least a month old". Without further file-tagging, this isn't possible to automate. So personally, I just let them build up on the server and occasionally clean things up manually if I feel the need. "Manually" in this case could still be a script, but the point is that it is run manually, not after each release.

You could imagine building a system that tracks versions and fully automates this, but that system will end up somewhat opinionated which is why I don't think there is one standard way in which everyone does this.

Edit: There's something else to keep in mind, too. Because the file names are hashed, if they don't change the same file might be relevant for a long time, possibly years. This is especially common for images. If your deployment process only uploads new files, you can never delete anything reliably. However if you always upload all files from the latest build, overwriting what is already on the server in the case of conflicts, that will enable you to cleanup occasionally, if you want.

Related