dotnet / dotnet/sdk

Compressed staticwebassets from a class library get incorrect Cache-Control header

Open
#54,907 0 comments 0 reactions 0 assignees View on GitHub
Area-AspNetCore untriaged
Dominant language
C#
Stars
3.2k
Forks
1.3k
PR merge metrics
PR metrics pending

Description

### Describe the bug

When publishing a Blazor WASM project with compression enabled and that includes a reference to a class library that includes static web assets, the compression step creates compressed variants of the static files, such as `library.fingerprint.bundle.scp.css.gz`, and includes them in the `app.staticwebassets.endpoints.json` file. However, the `Cache-Control` header included in the JSON is `no-cache` rather than inheriting the `Cache-Control` header specified for the uncompressed version from the library.

Example snippet of the generated MSBuild item found in the library's NuGet package `build/Microsoft.AspNetCore.StaticWebAssetEndpoints.props`:

```xml

$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)..\staticwebassets\Phoenix.WebUI.BlazorComponents.57b10uu31a.bundle.scp.css'))


```

### Steps to reproduce

- Create a Blazor component library that includes static web assets
- Create a Blazor WASM application that uses the component library, leaving compression enabled
- Publish the WASM application

### Expected behavior

This results in less efficient caching, requiring cache validation round trips in almost all cases, since almost all requests will include GZip or Brotli in the `Accept-Encoding` header. Instead, we would expect the compressed variants to also have a `Cache-Control` header of `max-age=31536000, immutable`.

### Actual behavior

Example snippet from the `staticwebassets.endpoints.json` generated on publish of the consuming application:

```json
[
{
"Route": "_content/Phoenix.WebUI.BlazorComponents/Phoenix.WebUI.BlazorComponents.57b10uu31a.bundle.scp.css",
"AssetFile": "_content/Phoenix.WebUI.BlazorComponents/Phoenix.WebUI.BlazorComponents.57b10uu31a.bundle.scp.css",
"Selectors": [
],
"ResponseHeaders": [
{
"Name": "Cache-Control",
"Value": "max-age=31536000, immutable"
},
{
"Name": "Content-Length",
"Value": "6263"
},
{
"Name": "Content-Type",
"Value": "text/css"
},
{
"Name": "ETag",
"Value": "\"8cYXUFws7fVyXqWd6FRTHueaeE++uvH+c5N/GKCLNU0=\""
},
{
"Name": "Last-Modified",
"Value": "Thu, 11 Jun 2026 13:33:06 GMT"
},
{
"Name": "Vary",
"Value": "Accept-Encoding"
}
],
"EndpointProperties": [
{
"Name": "fingerprint",
"Value": "57b10uu31a"
},
{
"Name": "integrity",
"Value": "sha256-8cYXUFws7fVyXqWd6FRTHueaeE++uvH+c5N/GKCLNU0="
},
{
"Name": "label",
"Value": "_content/Phoenix.WebUI.BlazorComponents/Phoenix.WebUI.BlazorComponents.bundle.scp.css"
}
]
},
{
"Route": "_content/Phoenix.WebUI.BlazorComponents/Phoenix.WebUI.BlazorComponents.57b10uu31a.bundle.scp.css.br",
"AssetFile": "_content/Phoenix.WebUI.BlazorComponents/Phoenix.WebUI.BlazorComponents.57b10uu31a.bundle.scp.css.br",
"Selectors": [
],
"ResponseHeaders": [
{
"Name": "Cache-Control",
"Value": "no-cache"
},
{
"Name": "Content-Encoding",
"Value": "br"
},
{
"Name": "Content-Length",
"Value": "1290"
},
{
"Name": "Content-Type",
"Value": "text/css"
},
{
"Name": "ETag",
"Value": "\"nqZOb1s30ln4wqLIVI1H0Q0C/7D+KYK/wIjsuBooNaE=\""
},
{
"Name": "Last-Modified",
"Value": "Tue, 16 Jun 2026 16:19:19 GMT"
},
{
"Name": "Vary",
"Value": "Accept-Encoding"
}
],
"EndpointProperties": [
{
"Name": "integrity",
"Value": "sha256-nqZOb1s30ln4wqLIVI1H0Q0C/7D+KYK/wIjsuBooNaE="
}
]
},
{
"Route": "_content/Phoenix.WebUI.BlazorComponents/Phoenix.WebUI.BlazorComponents.57b10uu31a.bundle.scp.css.gz",
"AssetFile": "_content/Phoenix.WebUI.BlazorComponents/Phoenix.WebUI.BlazorComponents.57b10uu31a.bundle.scp.css.gz",
"Selectors": [
],
"ResponseHeaders": [
{
"Name": "Cache-Control",
"Value": "no-cache"
},
{
"Name": "Content-Encoding",
"Value": "gzip"
},
{
"Name": "Content-Length",
"Value": "1518"
},
{
"Name": "Content-Type",
"Value": "text/css"
},
{
"Name": "ETag",
"Value": "\"FqgZf1Eq993iIwE+/JyhbEkrAVjssAtBWmLkUyFtMiA=\""
},
{
"Name": "Last-Modified",
"Value": "Tue, 16 Jun 2026 16:19:05 GMT"
},
{
"Name": "Vary",
"Value": "Accept-Encoding"
}
],
"EndpointProperties": [
{
"Name": "integrity",
"Value": "sha256-FqgZf1Eq993iIwE+/JyhbEkrAVjssAtBWmLkUyFtMiA="
}
]
}
]
```

### Is this a regression?

_No response_

### Are there any workarounds?

I imagine some manual MSBuild targets could be used to adjust the StaticWebAssetEndpoint items after compression but before final publish, but I haven't tried to piece this together yet.

### dotnet --info output

```console
.NET SDK:
Version: 10.0.301
Commit: 96856fd726
Workload version: 10.0.300.3
MSBuild version: 18.6.4+96856fd72

Runtime Environment:
OS Name: Windows
OS Version: 10.0.26200
OS Platform: Windows
RID: win-x64
Base Path: C:\Program Files\dotnet\sdk\10.0.301\

.NET workloads installed:
[android]
Installation Source: SDK 10.0.300, VS 18.6.11828.311
Manifest Version: 36.1.53/10.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\10.0.100\microsoft.net.sdk.android\36.1.53\WorkloadManifest.json
Install Type: Msi

[ios]
Installation Source: SDK 10.0.300, VS 18.6.11828.311
Manifest Version: 26.5.10284/10.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\10.0.100\microsoft.net.sdk.ios\26.5.10284\WorkloadManifest.json
Install Type: Msi

[maccatalyst]
Installation Source: SDK 10.0.300, VS 18.6.11828.311
Manifest Version: 26.5.10284/10.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\10.0.100\microsoft.net.sdk.maccatalyst\26.5.10284\WorkloadManifest.json
Install Type: Msi

[maui-windows]
Installation Source: SDK 10.0.300, VS 18.6.11828.311
Manifest Version: 10.0.20/10.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\10.0.100\microsoft.net.sdk.maui\10.0.20\WorkloadManifest.json
Install Type: Msi

[wasm-tools]
Installation Source: SDK 10.0.300
Manifest Version: 10.0.108/10.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\10.0.100\microsoft.net.workload.mono.toolchain.current\10.0.108\WorkloadManifest.json
Install Type: Msi

Configured to use workload sets when installing new manifests.

Host:
Version: 10.0.9
Architecture: x64
Commit: 901ca94124

.NET SDKs installed:
8.0.422 [C:\Program Files\dotnet\sdk]
9.0.306 [C:\Program Files\dotnet\sdk]
9.0.308 [C:\Program Files\dotnet\sdk]
9.0.315 [C:\Program Files\dotnet\sdk]
10.0.109 [C:\Program Files\dotnet\sdk]
10.0.301 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
Microsoft.AspNetCore.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 8.0.22 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 8.0.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 9.0.10 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 9.0.11 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 9.0.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 10.0.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.22 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.28 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 9.0.10 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 9.0.11 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 9.0.17 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 10.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 8.0.22 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 8.0.28 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 9.0.10 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 9.0.11 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 9.0.17 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 10.0.9 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Other architectures found:
x86 [C:\Program Files (x86)\dotnet]
registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]

Environment variables:
DOTNET_NOLOGO [true]
DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION [true]

global.json file:
Not found

Learn more:
https://aka.ms/dotnet/info

Download .NET:
https://aka.ms/dotnet/download
```

### IDE version

_No response_

### Other details

_No response_

Contributor guide

No contributing guide indexed for this repository

Research direction

Reproduce the issue by publishing a Blazor WASM app that references a component library with static web assets and compression enabled. Compare the library's build/Microsoft.AspNetCore.StaticWebAssetEndpoints.props metadata with the generated app.staticwebassets.endpoints.json; done means the .br and .gz endpoints inherit the uncompressed asset's Cache-Control value.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, wasm
Domain
build-system, web-dev
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.