Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Blazor WebAssembly, how to include hash in static file link/script reference in index.html for cache-busting?

In server-side ASP.NET, we can do asp-append-version=true on static assets in a .cshtml file in order to automatically append a hash of the file to the filename. But, in Blazor WebAssembly, this doesn't work, which makes sense because I have a simple index.html file that bootstraps Blazor and references static files, not a server-modified file.

So is there a good way in Blazor WebAssembly's index.html file to append a hash to the URL of a static file, similar in outcome to the old asp-append-version=true? For example, to make <link href="css/site.css" rel="stylesheet" /> become <link href="css/site.css?v=1234abc..." rel="stylesheet" />, and thus changes to site.css on deployment will result in all clients GETting the newly changed static file, rather than relying on cache?

like image 247
Patrick Szalapski Avatar asked May 12 '20 02:05

Patrick Szalapski


1 Answers

I came up with a workaround for this. I have created a controller that will handle the request, read the index.html, search and replace a "{version}" placeholder and then return the content.

First step is to modify the Startup.cs:

            //endpoints.MapFallbackToFile("index.html");
            endpoints.MapFallbackToController("Index", "Home");

Then create a controller like this one:

public class HomeController : Controller
{
    private static string _processedIndexFile;
    private readonly IWebHostEnvironment _webHostEnvironment;

    public HomeController(IWebHostEnvironment webHostEnvironment)
    {
        _webHostEnvironment = webHostEnvironment;
    }

    [ResponseCache(CacheProfileName = CacheProfileNames.NoCache)]
    public IActionResult Index()
    {
        return ProcessAndReturnIndexFile();
    }

    private IActionResult ProcessAndReturnIndexFile()
    {
        if (_processedIndexFile == null)
        {
            IFileInfo file = _webHostEnvironment.WebRootFileProvider.GetFileInfo("index.html");
            _processedIndexFile = System.IO.File.ReadAllText(file.PhysicalPath);
            _processedIndexFile = _processedIndexFile.Replace("{version}", AppInfo.CompiledOn.ToString("yyyy'-'MM'-'dd'-'HH'-'mm'-'ss"));
        }
        return Content(_processedIndexFile, "text/html");
    }
}

And finally inside the index.html file, use urls like:

<link href="css/app.min.css?v={version}" rel="stylesheet" />

This also allows you to do some other things before returning the file inside the Index method, like checking if falling back to index.html is correct for the current request:

        // Check for incorrect fallback routes
        if (Request.Path.Value?.Contains("api/") == true)
            return NotFound();
like image 65
Augusto Barreto Avatar answered Nov 07 '22 20:11

Augusto Barreto