I det här inlägget beskrivs hur du kan minifiera och cacha statiska filer i ASP.NET Core. Du kanske vill göra detta för att göra din webbplats snabbare och därmed förbättra hemsidan placering sökresultaten (SEO).
En viktig sak att tänka på innan du cachar statiska filer är att du behöver en metod för att invalidera cacheminnet när dina statiska filer ändras. Varje statisk fil som du sparar kan ha ett unikt namn som ett GUID, du kan också lägga till en parameter till filnamnet som är unik för varje ny version av filen. Du kan använda en kombination av dessa metoder, bilder kan ha GUID-namn och du kan använda en versionsparameter för andra filer.
Bundler och minifier
Jag använder ett NuGet-paket som heter BuildBundlerMinifier som är skapat av Mads Kristensen, detta verktyg används för att minifiera statiska filer i mina projekt. Du behöver också tillägget Bundler & Minifier i Visual Studio för att kunna köra en uppgift som minifierar filer (Task Runner Explorer). När du har installerat detta paket läggs en json-fil med namnet bundleconfig.json till ditt projekt i Visual Studio. Du kan redigera den här filen direkt eller minimera statiska filer genom att högerklicka på dem i Visual Studio. Innehållet i filen bundleconfig.json ser ut ungefär så här.
[
{
"outputFileName": "wwwroot/css/admin_default.min.css",
"inputFiles": [ "wwwroot/css/admin_default.css" ]
},
{
"outputFileName": "wwwroot/css/admin_layout.min.css",
"inputFiles": [ "wwwroot/css/admin_layout.css" ]
}
]
Invalidera cacheminnet
Vi behöver en metod för att invalidera cacheminnet för statiska filer. Vi har en gemensam klass där vi har injicerat IMemoryCache och IWebHostEnvironment, vi skapar en referens till en IFileProvider file_provider från environment.
public CommonServices(IMemoryCache cache, IWebHostEnvironment environment)
{
this.cache = cache;
this.environment = environment;
this.file_provider = environment.WebRootFileProvider;
} // End of the constructor
Vår metod för att invalidera cacheminnet lagrar den relativa sökvägen till den statiska filen och en MD5-hash för filen i minnet. Vår file_provider kommer att bevaka förändringar avseende filen och se till att filen får en ny versionsparameter.
/// <summary>
/// Get a file path with a version hash
/// </summary>
public string GetFilePath(string relative_path)
{
// Create a variable for a hash
string hash = "";
// Get the hash
if(this.cache.TryGetValue(relative_path, out hash) == false)
{
// Create an absolute path
string absolute_path = this.environment.WebRootPath + relative_path;
// Make sure that the file exists
if(File.Exists(absolute_path) == false)
{
return relative_path;
}
// Create cache options
MemoryCacheEntryOptions cache_entry_options = new MemoryCacheEntryOptions();
// Add an expiration token that watches for changes in a file
cache_entry_options.AddExpirationToken(this.file_provider.Watch(relative_path));
// Create a hash of the file
using (MD5 md5 = MD5.Create())
{
using (Stream stream = File.OpenRead(absolute_path))
{
hash = Convert.ToBase64String(md5.ComputeHash(stream));
}
}
// Insert the hash to cache
this.cache.Set(relative_path, hash, cache_entry_options);
}
// Return the url
return $"{relative_path}?v={hash}";
} // End of the GetFilePath method
Lägg till referenser till statiska filer
Vi använder vår GetFilePath-metod när vi lägger till referenser till statiska filer i vår layoutvy, för bilder kan det vara bättre att använda en tidsstämpel som versionsparameter om bildernas namn inte är unika. Bilder kan vara stora och många, spara tidstämpeln i din databas och lägg till den som en versionsparameter.
<environment names="Development">
<link href="@this.tools.GetFilePath(imageUrls.Get("small_icon"))" rel="icon" type="image/x-icon" />
<link href="@this.tools.GetFilePath("/css/standard_layout.css")" media="screen and (min-width:1344px)" rel="stylesheet" />
<link href="@this.tools.GetFilePath("/css/medium_layout.css")" media="only screen and (min-width:1024px) and (max-width:1343px)" rel="stylesheet" />
</environment>
<environment names="Staging,Production">
<link href="@this.tools.GetFilePath(imageUrls.Get("small_icon"))" rel="icon" type="image/x-icon" />
<link href="@this.tools.GetFilePath("/css/standard_layout.min.css")" media="screen and (min-width:1344px)" rel="stylesheet" />
<link href="@this.tools.GetFilePath("/css/medium_layout.min.css")" media="only screen and (min-width:1024px) and (max-width:1343px)" rel="stylesheet" />
</environment>
Tjänster
Vi måste lägga till en tjänst för minnescache i metoden ConfigureServices i klassen StartUp för att kunna cacha relativa sökvägar och en MD5-hash.
// Add memory cache
services.AddDistributedMemoryCache();
Vi måste också lägga till headers till statiska filer som visar att de kan cachas av en webbläsare och hur länge de kan cachas. Vi lägger till detta i metoden Configure i klassen StartUp.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// Use static files
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
{
// Cache static files for 30 days
ctx.Context.Response.Headers.Append("Cache-Control", "public,max-age=2592000");
ctx.Context.Response.Headers.Append("Expires", DateTime.UtcNow.AddDays(30).ToString("R", CultureInfo.InvariantCulture));
}
});
// More code ...
} // End of the Configure method
Du kan inspektera headers för statiska filer i Chrome under Nätverk i utvecklarverktyget för att kontrollera att de har korrekta värden.