Search code examples
angularasp.net-mvccaching

Angular [12] seems not to cache JavaScript files between visits


First, off I should mention this app is a bit different where since the site is a hybrid of MVC/Knockout (legacy app) and Angular. Since we do not have a token-based auth system in place, instead, an MVC controller serves up the Angular app. (unfortunately not something that can be changed any time soon)

So the user will be navigating from MVC/KO pages to an Angular app and vice versa.

I noticed that each time the Angular app gets served, the compiler-generated JavaScript files get loaded (thus, it's not cached)

I learned Angular on the fly as the need arose, so not sure if the problem is with some angular setting or the way we serve up the angular app.

Probably not the most elegant solution, but this is the code that will serve up the angular app:

public ActionResult Index(string path) {

    path = string.IsNullOrEmpty(path) ? "index.html" : path;

    var baseDirUri = new Uri(Server.MapPath("~") + "\\" + config.GetAppSetting("AngularAppPath"));

    // try to prevent directory traversal by resolving \..\ etc into an absolute path and then converting back into a Uri and testing the base dir
    // (it should be handled already by the browser and by the framework, but just in case)
    var absoluteFilePath = new Uri(baseDirUri, path.Replace("/", "\\")).AbsolutePath;
    var fileUri = new Uri(absoluteFilePath);

    if (!baseDirUri.IsBaseOf(fileUri))
    {
        return new HttpUnauthorizedResult();
    }

    if (!System.IO.File.Exists(fileUri.AbsolutePath))
    {
        return new HttpNotFoundResult();
    }

    var contentType = GetContentType(fileUri.AbsolutePath);
    if (contentType.Contains("image/"))
    {
        return File(fileUri.AbsolutePath, contentType);
    }

    var doc = System.IO.File.ReadAllText(fileUri.AbsolutePath);
    return Content(doc, contentType);
}

Solution

  • To do the JavaScript caching, you can try to add the following code in your web.config file:

    <system.webServer>
        <staticContent>
            <clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="1.00:00:00" />  <!-- 1 Day -->
        </staticContent>
    </system.webServer>
     
    

    Another option you can try, add the following code to the Index action:

    var cache = new System.Web.Caching.Cache();
    var cacheKey = "AngularAppCacheKey";
    var cacheDuration = 60 * 60 * 24 * 7; // 1 week
    var cacheItem = cache.Get(cacheKey);
    if (cacheItem != null)
    {
        return Content(cacheItem.ToString(), contentType);
    }
    
    var doc = System.IO.File.ReadAllText(fileUri.AbsolutePath);
    cache.Insert(cacheKey, doc, null, DateTime.Now.AddSeconds(cacheDuration), System.Web.Caching.Cache.NoSlidingExpiration);
    return Content(doc, contentType);
     
    

    I hope this helps.