Dealing with hashed filenames

13 Sep 2017

Most Single Page Applications framework like Angular, React etc., requires module builders like Webpack, Browserify, SystemJs etc., to build the modules into browser understandable web format like es5. These module builders usually comes packed with cache busting feature by including content MD5 hashes in the generated output bundles.

Why cache busting ?
It is a best practice to set a long expiration date for static assets like scripts, css, images and other medias. So it gets cached on user system. This greatly improves the website performance and avoids re-downloading of already downloaded assets when the user visits the site for second/third time. No requests will be made to the actual server if the contents exists in the cache.

But the benefit comes along with a problem: consider if the contents has changed during latest code deployment. There is no real way for a browsers to identify this change.

Including hash value in filename helps the web browsers to identify the change in the file content or there by asset URL change, when an user revisits the same website. This change in Uniform Resource Locator forces the browser to fetch modified resource without depending on the cached asset item.

We can specify filename formats like [name].[hash].js, in the webpack configuration. which results in the output files generated with filenames like vendor.15ccb83...a2ab8276d.js. This makes the cache busting pretty easy to implement. Problem comes when we have to link this items in our .netcore mvc Razor templates/views (.cshtml) file.

Asp .Net Core MVC is primarily designed with SPA developers and node NPM packages & their build systems in mind, so it offers an easy way to include media artifacts/assets generated by the module systems through mvc tag helpers. So in order to add the script file with the hashname to the <script> src; would require following syntax

<script type="text/javascript" asp-src-include="vendor.*.js"></script>

This wildcard '*' will match the hashed part of the filename. Above tag helper attribute 'asp-src-include' requires us to add following includes to _ViewImports.cs, which will allow you to use the helper tags in all RazorViews in that containing folder's scope.

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

Further, the development setup may need us to specify the files or assets without the hashes in development machines, because in Dev. mode the module builder will automatically serves the files HOT without caching. But when it is deployed to staging/production server, it requires cache busting to be enables. As mentioned earlier, .Net Core is more friendly kiss with the front end development model. So it offer following <environment> tag inside which we can embed the resources as required for each environments like below

<environment names="Development">
    <script type="text/javascript" src="/vendor.js"></script>
<environment names="Production,Staging">
    <script type="text/javascript" asp-src-include="~/vendor*.js"></script>

Hope this helps you with your SPA app setup or simple cache busting for your classic .net core app

Related Posts