DEV Community

Cover image for Ow you need to clear your browser cache to view the changes… never again (with umbraco CMS)
Tim Geyssens
Tim Geyssens

Posted on

2

Ow you need to clear your browser cache to view the changes… never again (with umbraco CMS)

Yes yes I’ve started blogging again (I’ll do a intro post soon), the reason is I want to share usefull #umbraco stuff again. (remember http://www.nibble.be/) …

So as an (#umbraco) webdev we make css and js (client side) changes to our clients solutions… but how often have you need to tell your client to refresh the browser cache to view the most recent changes on their site?

Of course you can do some manual appending of params like .css?v=1 , .css?v=anotherupdate but chances are you’ll forget this… and of course a mismatch between markup and js/css can lead to an ugly looking/even broken website

Wouldn’t it be nice if this could be automated, so each time a change is detected in the js/css file you are certain the client and site visitors get the correct version.

This can be done by adding a simple file hasher (c# code)

using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace MyUmbracWebsite
{
public static class StaticFileHasher
{
private static Dictionary<string, string> FileHashes { get; set; }
public static string Hash(string path)
{
if (String.IsNullOrEmpty(path) || !FileHashes.ContainsKey(path))
{
return null;
}
return FileHashes[path];
}
public static void HashFiles(params string[] directories)
{
FileHashes = new Dictionary<string, string>();
var FileExtensions = new string[] { "*.css", "*.js", };
using (var md5 = MD5.Create())
{
foreach (var directory in directories)
{
foreach (var extension in FileExtensions)
{
foreach (var file in Directory.EnumerateFiles(directory, extension))
{
byte[] hash;
using (var stream = File.OpenRead(file))
{
hash = md5.ComputeHash(stream);
}
StringBuilder sOutput = new StringBuilder(hash.Length);
for (var i = 0; i < hash.Length - 1; i++)
{
sOutput.Append(hash[i].ToString("X2"));
}
FileHashes.Add(Path.GetFileName(file), sOutput.ToString().ToLower());
}
}
}
}
}
}
}

This bit of code will generate a unique hash based on a file (contents) and add it to a Dictionary (limited to .css and .js files found in specified dirs), key being the name of the file.
Of course we need to run this once on site startup…(so we get a hash for all files we want, feeding in directories)

In Umbraco v7 this can be done with an ApplicationEventHandler

using Umbraco.Core;
namespace MyUmbracoWebsite
{
public class Startup : ApplicationEventHandler
{
protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
StaticFileHasher.HashFiles(umbracoApplication.Server.MapPath("~/css"), umbracoApplication.Server.MapPath("~/js"));
}
}
}
view raw Startup.cs hosted with ❤ by GitHub

In Umbraco v8 with the ApplicationComponent stuff

public class ApplicationComposer : ComponentComposer<ApplicationComponent>, IUserComposer
{
public override void Compose(Composition composition)
{
StaticFileHasher.HashFiles(umbracoApplication.Server.MapPath("~/css"), umbracoApplication.Server.MapPath("~/js"));
base.Compose(composition);
}
}

So now in the layout (or wherever I’m linking to the .css . js files) You can add:

/css/app.css?hash=@StaticFileHasher.Hash(“app.css”)

this then get’s outputted as

/css/app.css?hash=da1cc0b5fb4e777fe556fb8d61168c

(of course not with the same hash)

And when the file contents changes after a change/deploy the unique hash will also change … Tada! You are now sure your client and site visitors get the latest css/js

AWS Q Developer image

Your AI Code Assistant

Automate your code reviews. Catch bugs before your coworkers. Fix security issues in your code. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

Top comments (2)

Collapse
 
benehudson profile image
benehudson

Doesn't requirejs and requirecss already accomplish this? Along with minification and specifying the order the files are stacked?

I was walking through some of my code with a non-umbraco dev recently, and he was impressed by requirejs and requirecss.

Collapse
 
timgeyssens profile image
Tim Geyssens

maybe... but this is for the frontend... so not sure everybody is using that dependency (requirejs and requirecss )

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay