Cache bursting or invalidating TypeScript files when using SystemJS module loaders

This article assumes that you are a web developer and have some prior knowledge of TypeScript, ASP.Net core, gulp, and SystemJS (module loader). It explains what cache bursting is and how to apply the cache bursting for TypeScript files loaded using SystemJS module loaders. This post Utilizes a third party open source library systemjs-cachebuster which patches SystemJS loader with hash values of each module, thus enforcing the browser to fetch only the modules that has changed from the server.

One of the ways to improve the performance of a web page, to cache static resources like images, style sheets, and scripts. By using caching, the number of requests sent to the server is reduced thereby page load performance increases. One of the important things to consider while caching a static resource, to provide a way to burst (invalidate) a cache.

Cache bursting in simple terms means forcing a client to reload the latest version of the resource from the server, when a resource is modified instead of using a cached copy of the resource from web browser cache. A simple technique to achieve this, to append a version as a query parameter in URL. By appending a URL browser detects the modification in the file, due to the difference in file URL and so it sends a request to the server to fetch the new resource instead of loading from cache.

The example discussed here will help you understand the need for cache bursting further.

Consider a website in which there is an option to upload a profile image. This website caches user profile image for a period of one year at client side (i.e.,) in the user browser cache. Profile images of users are stored and retrieved based on their usernames, so image URL to fetch an image from the server would be profile/pic/username.jpg.

Now, consider a case where a user uploaded an image. After a one-month period, the same user changed profile image. So, in server image of the user has been replaced. But to access that image URL is still same even after changing image (profile/pic/username.jpg). Now, another person who has already viewed that user profile a month back when visits same user profile again now, the web browser of user finds no difference in profile image URL, so browser still displays old image even though the server has a different image. The reason is user browser has already cached image for one year, remember I told before that website had a mechanism to store an image for a period of one year at the client browser. When a user visited a page a month later, the URL of profile image is not changed the browser does not find any difference and does not send a request to the server to fetch user image again.

One way to overcome this, user must clear cache (hard refresh) of web page and load profile, but on doing so it takes more time to load a website as the browser has to fetch all resources of the website. Doing a hard refresh is something which most of the users do not prefer and some are not aware of it. This is where the cache bursting comes to play.

A simple way to solve this problem to append a file version as a query parameter in the URL so that browser can find a difference in URL. After appending a version, the URL would become profile/pic/username.jpg?v1.0, so when an image is changed actual URL would remain same, only version part will be changed (profile/pic/username.jpg?v2.0). By using this technique we are forcing a browser to fetch a resource if it is changed, the browser finds a difference in URL, and a person visits a user profile find the updated profile image without doing a hard refresh. Similar scenario and concept apply to any static resources like CSS, JavaScript, and Typescript. Using cache bursting technique caching can be utilized at its best and store static resource for an indefinite time in the client browser.

In the previous version of ASP.NET MVC, this was a bit easier when dealing with JavaScript file. The ASP.NET MVC framework provided an inbuilt mechanism for bundling and minification, and so cache buster query string has been automatically created. In ASP.Net core there is not an inbuilt support for cache bursting TypeScript file using SystemJS. Although ASP.NET Core has new support in the form of asp-append-version attribute, this is not useful when Typescript’s files are loaded using SystemJs. The new attribute can be used for CSS, images, and JavaScript. Another approach to overcome this for TypeScript files to include a file version in URL and change it manually every time when a new version of the site is released.

Using an automated way, a third party open source library systemjs-cachebuster which patches SystemJS loader with hash values of each module enforcing the browser to reload only the modules that were changed. System-cachebuster would work directly without any modification if you are using ASP.NET MVC but to make it work for ASP.Net core, need to do some modification in the original version. This modification is simple, requires just a small change in folder path in original plugin file, changes required because file structure of ASP.Net core uses “wwwroot” directory which is different from previous ASP.NET file structure. So, by using systemjs-cachebuster and some gulp-based task at the end, will be able to generate version-based TypeScript files.

The following steps explains, how to use it in the actual project. Using a simple ASP.Net core project which uses a simple TypeScript file to alert a Hello. A complete working sample can be checked in GitHub.

Below are steps to use systemjs-cachebuster in the application:

Assume you have already created an Asp.Net core web project and setup typescript, SystemJS and gulp. For showcase purpose, I have used a default MVC template and added a simple typescript file to alert a Hello in the sample.

Step 1:

Include “systemjs-cachebuster” and “gulp-replace” packages in package.json file of your project.

Step 2:

After the package.json file has been saved, Visual Studio will install new packages automatically. Navigate to “\node_modules\systemjs-cachebuster\src\“ folder of your project and copy these two files “system.cachebuster.js” and “system.cachebuster.gulp.js”. Now, paste these two copied files in your project at this location “\wwwroot\js\plugins\”.

Note: Use these files directly from node_modules folder, but need to change the folder path in “system.cachebuster.js” file we are copying it to our project. In the sample you can find it here.

Step 3:

Now, need to do a small modification in system.cachebuster.js file to change the folder path. You can find code modifications changes here. In code modification you will find folder location changed to “/js/others/” this is where we will be placing auto-generated system.cachebuster.json file. This file is used as a lookup file by SystemJS to find file hash to append in URL.

Note: No need to commit this file, it is auto-generated by the cache-buster plugin.

Step 4:

Next, to write two simple gulp tasks for run a systemjs-cachebuster plugin. First task generates “system.cachebuster.json” file. Second task to copy this auto-generated file to “wwwroot/js/others/” folder. The second task is written because in ASP.NET core everything inside wwwroot is accessible by the website, so writing a second task for copying auto-generated file to wwwroot directory, it is included automatically when the site is published.

You can find the complete code for gulp task in gulpfile.js file in the sample.

Step 5:

Now, include following scripts in your project layout page:

system.cachebuster.js: actual third-party plugin file.

system.cachebuster.json: auto-generated hash lookup file generated by system.cachebuster plugin.

app.ts: a file which is used by the website to alert a “Hello” message.

Testing:

Below steps shows you how to test whether cache-buster is integrated into our project or not:

1. Build and run this sample.

2. After running you will find that a file named “system.cachebuster.json” will be automatically generated at this location “\wwwroot\js\others”.

3. Now, open any web browser and open inspector window, you will find that your TypeScript file includes a hash in URL. These hash is auto-generated and changes every time when a content of the file is changed. Before using this plugin, if a file content was changed URL will not include hash and will look like “app.ts”, so the browser does not fetch a new copy of the resource from the server if it was cached. After using this a hash is appended to URL, forces the browser to fetch the new resource . So, by this way, achieve the cache busting.

Summary

systemjs-cachebuster helps to simplify the process of versioning TypeScript files and provides an easy automated way to invalidate/cache burst TypeScript files, by appending file hash in URL. Credit to third-party library systemjs-cachebuster.

Further reading

To know more about caching static resources in ASP.Net core refer to these articles:

https://andrewlock.net/adding-cache-control-headers-to-static-files-in-asp-net-core/

https://www.softfluent.com/blog/dev/Caching-static-resources-forever-with-ASP-NET-Core

Tech Enthusiast, Full Stack Software Engineer, Product Manager, Engineering Enterprise SaaS product

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store