diff --git a/Src/TournamentCalendar/TournamentCalendar.csproj b/Src/TournamentCalendar/TournamentCalendar.csproj index 2cb144b..d6f688d 100644 --- a/Src/TournamentCalendar/TournamentCalendar.csproj +++ b/Src/TournamentCalendar/TournamentCalendar.csproj @@ -71,7 +71,9 @@ - + + all + @@ -167,4 +169,4 @@ - \ No newline at end of file + diff --git a/Src/TournamentCalendar/WebAppStartup.cs b/Src/TournamentCalendar/WebAppStartup.cs index 345f633..159cbc3 100644 --- a/Src/TournamentCalendar/WebAppStartup.cs +++ b/Src/TournamentCalendar/WebAppStartup.cs @@ -147,6 +147,29 @@ public static void ConfigureServices(WebApplicationBuilder builder) #endregion + #region *** Response compression for non-SDK static files (e.g. /lib/*) *** + + // MapStaticAssets() serves pre-compressed .br/.gz for SDK-managed assets (e.g. css/site.min.css). + // UseResponseCompression handles on-the-fly compression for all other files (e.g. /lib/bootstrap/). + services.AddResponseCompression(options => + { + options.EnableForHttps = true; + options.Providers.Add(); + options.Providers.Add(); + options.MimeTypes = Microsoft.AspNetCore.ResponseCompression.ResponseCompressionDefaults.MimeTypes.Concat( + [ + "application/javascript", + "text/css", + "image/svg+xml" + ]); + }); + services.Configure(o => + o.Level = System.IO.Compression.CompressionLevel.Fastest); + services.Configure(o => + o.Level = System.IO.Compression.CompressionLevel.Fastest); + + #endregion + #region *** Cookie Authentication *** services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) @@ -158,10 +181,8 @@ public static void ConfigureServices(WebApplicationBuilder builder) options.AccessDeniedPath = new PathString("/auth/denied"); options.Cookie.Name = ".TournamentsAuth"; }); - - #endregion - #region *** MailMergeLib as a service *** + #endregion services.AddMailMergeService( options => @@ -179,8 +200,6 @@ public static void ConfigureServices(WebApplicationBuilder builder) } options.MessageStore = fms; }); - - #endregion } private static void ConfigureLlblgenPro(Data.IDbContext dbContext, IWebHostEnvironment environment) @@ -215,6 +234,9 @@ public static void Configure(WebApplication app) app.UseHttpsRedirection(); + // Must be before UseStaticFiles and MapStaticAssets to compress non-SDK static files + app.UseResponseCompression(); + var cultureInfo = CultureInfo.GetCultureInfo("de-DE"); CultureInfo.DefaultThreadCurrentCulture = CultureInfo.CurrentCulture = cultureInfo; @@ -278,24 +300,14 @@ public static void Configure(WebApplication app) #region *** Static files *** - // For static files in the wwwroot folder + // For static files in the wwwroot folder. + // UseDefaultFiles must come before MapStaticAssets/UseStaticFiles. app.UseDefaultFiles(); - app.UseStaticFiles(new StaticFileOptions - { - OnPrepareResponse = ctx => - { - var headers = ctx.Context.Response.GetTypedHeaders(); - headers.CacheControl = new CacheControlHeaderValue - { - Public = true, - MaxAge = TimeSpan.FromDays(30) - }; - } - }); - // For static files using a content type provider: + // Serves all standard static files (including /lib/*) with cache headers. + // .webmanifest is added so it doesn't cause a 404. + // MapStaticAssets() below handles SDK-managed assets with pre-compressed .br/.gz variants. var provider = new Microsoft.AspNetCore.StaticFiles.FileExtensionContentTypeProvider(); - // Make sure .webmanifest files don't cause a 404 provider.Mappings[".webmanifest"] = "application/manifest+json"; app.UseStaticFiles(new StaticFileOptions { @@ -322,8 +334,11 @@ public static void Configure(WebApplication app) app.UseAuthentication().UseAuthorization(); // The net6.0+ top level replacement for app.UseEndpoints(...) // (WebApplication implements IEndpointRouteBuilder) + // Serves pre-compressed (.br/.gz) static web assets generated at publish time. + // Cache headers are handled automatically via asset fingerprinting. + app.MapStaticAssets(); app.MapControllers(); - app.MapRazorPages(); + app.MapRazorPages().WithStaticAssets(); // Suppress exceptions when the connection is closed by the client app.UseMiddleware();