Adding Cache safe links to a Grunt build in ASP.NET Core 1.0

The post shows how to add cache safe links and scripts to a HTML file using grunt in a ASP.NET Core 1.0 application. The post uses the grunt build configuration from this blog, ( ASP.NET Core 1.0 Typescript AngularJS application with a grunt production configuration ).

Code: https://github.com/damienbod/AspNet5TypescriptProductionGrunt

2016.07.01: Updated to ASP.NET Core 1.0 RTM
2016.06.11: Updated to ASP.NET Core 1.0 RC2
2015.11.18: Updated to ASP.NET Core 1.0 RC1
2015.10.20: Updated to ASP.NET Core 1.0 beta 8

Strategy

When updating the production deployment, or continuous builds, in a web application, the old versions of the scripts and the CSS files will still be used, because these are saved in the client’s browser cache and the new ones have the same URLs. To solve this, a version hash is used to force the client to load the new files. The following configuration changes the links for every build and every CSS, script file used by the client. If you have a web application with lots of users, this is not a good strategy as you only want the browser to download the new changed files and not all the files. For example, the vendor CSS, script files will not change in every version.

It might also be helpful that the build version number is used and not a random hash for production releases. This would help with issue tracking.

Setup

In the application package.json file, the npm grunt-cache-control package is added. Visual Studio 2015 automatically downloads this for you.

{
    "name": "package",
    "version": "1.0.0",
    "private": true,
    "devDependencies": {
        "grunt": "0.4.5",
        "grunt-bower-install": "^1.6.0",
        "grunt-bower-task": "0.4.0",
        "grunt-contrib-cssmin": "^0.12.2",
        "grunt-contrib-uglify": "0.9.1",
        "grunt-contrib-watch": "0.6.1",
        "grunt-contrib-concat": "0.5.1",
        "uglify-js": "2.4.20",
        "grunt-ts": "4.0.1",
        "grunt-cache-control": "0.2.5"
    }
}

This grunt-cache-control npm package can then be used in the grunt file.

grunt.loadNpmTasks("grunt-cache-control");

A random hash string is created using the code from rob lauren’s blog. Thanks for this. This hash is then added to the version property. This creates a new random number for every build. This ensures that new links and scripts are always used in the browser with each build and not just with each version. This helps with continuous builds.

  grunt.initConfig({
        hash: '<%= ((new Date()).valueOf().toString()) + (Math.floor((Math.random()*1000000)+1).toString()) %>',          
        cache_control: {
            your_target: {
                source: ['wwwroot/index.html'],
                options: {
                    version: "<%= hash %>",
                    links: true,
                    scripts: true,
                    replace: true
                }
            }
        }

   });

The cache_control task is then added to the grunt registerTask which groups the different tasks together for the build.

grunt.registerTask('development', 
      [ 'ts', 
        'concat', 
        'uglify', 
        'cssmin', 
        'cache_control', 
        'watch'
      ]
);

grunt.registerTask('buildserver', 
     [ 'ts', 
       'concat', 
       'uglify', 
       'cssmin', 
       'cache_control'
     ]
);

The grunt task now creates new links with every grunt build.

gruntCache_01

The new links are added in the index.html file.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Demo typescript ASP.NET5</title>
        <link href="lib/mycode.min.css?v=1442604838788656950" rel="stylesheet" />
        <link href="lib/vendor.min.css?v=1442604838788656950" rel="stylesheet" />
    </head>
    <body>
    
        <div ng-app="myapp">
            <div ui-view></div>
        </div>

        <script type="text/javascript" src="lib/vendor.min.js?v=1442604838788656950"></script>
        <script type="text/javascript" src="lib/mycode.min.js?v=1442604838788656950"></script>
    </body>
</html>

Note

This is also a good solution if using Visual Studio 2013, because the required files have to be added to the cs project file. If new js and css are created each time, the csproj file would also need to be changed. This is not required with this configuration solving the client browser cache problem.

Links:

https://www.npmjs.com/package/grunt-cache-control

https://damienbod.wordpress.com/2015/05/12/asp-net-5-typescript-angularjs-application-with-a-grunt-production-configuration/

http://robandlauren.com/2013/08/14/busting-cache-with-grunt/

One comment

  1. Thanks for the link back to our blog Damien!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: