Repository navigation
Set explicit Cache-Control headers for the WebAssembly site - #16
Open
turbobobbytraykov wants to merge 3 commits into
Open
turbobobbytraykov wants to merge 3 commits into
turbobobbytraykov wants to merge 3 commits into
Conversation
Staging sent dotnet.js, blazor.boot.json, service-worker.js and uno-config.js without Cache-Control, so browsers and CloudFront picked their own freshness and could pair a new index.html with an old loader or config after a deploy. Everything now defaults to no-cache (revalidate; a 304 while unchanged). Content-addressed files - package_<sha1>/ except uno-config.js and uno-assets.txt, and fingerprinted _framework files - get public, max-age=31536000, immutable, only on 200/206/304. Errors get no-store. The index.html <location> blocks are covered by the root default and are removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # browser/SamplesBrowser/Platforms/WebAssembly/wwwroot/web.config
turbobobbytraykov
added a commit
that referenced
this pull request
Nov 11, 2026
Review follow-up: as #16 does for Brotli, the Gzip encoding rule now applies only to 200, 206 and 304 responses, so an IIS error page for a .gz path gets no Content-Encoding header. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gmurray81
approved these changes
Nov 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Staging sends
dotnet.js,blazor.boot.json,service-worker.jsanduno-config.jswithoutCache-Control, only with an ETag and Last-Modified. Browsers then pick a freshness time on their own (Chrome uses 10% of the file's age), so after a deploy a returning visitor can get the newindex.htmltogether with an old loader or an olduno-config.js:uno-config.jskeeps its URL when its content changes. The bootstrapper writes it intopackage_<sha1>/after it has computed the folder's hash.blazor.boot.jsonwith a plainfetch(). A stale copy names runtime files the deploy has already deleted, so the precache fails and the new worker never installs.Cache-Controlis kept for 24 hours. I haven't checked the policy or the error-caching TTL this distribution uses. Both decide how long CloudFront holdsno-cacheresponses and errors, so please confirm them before the production deploy.This PR makes the policy explicit in
web.config.Policy
Cache-Controlindex.html(also served for/and the sample deep links),service-worker.js,manifest.webmanifest,_framework/dotnet.js,_framework/blazor.boot.json,package_<sha1>/uno-config.jsanduno-assets.txt, andcode-viewer/*.jsonno-cache: browsers and proxies may keep a copy but revalidate it on every use, which is a 304 while it's unchangedpackage_<sha1>/, and_frameworkfiles with a 10-character fingerprintpublic, max-age=31536000, immutableno-store<clientCache cacheControlMode="DisableCache"/>at the application root.{REQUEST_FILENAME}), so the.brcopy and the plain file get the same policy. They apply only to 200, 206 and 304 responses.<location path="index.html*">blocks. Configuration follows the rewritten URL, so the root default now coversindex.htmland its copies..brpath no longer gets aContent-Encodingheader.allowedServerVariables, no<httpCompression>.In the .NET 9 build of vnext 0dbf623, 517 of the 857 URLs get the one-year policy (407 in the package folder, 110 in
_framework), and the other 340 stayno-cache. Counting the.brcopies, that's 1,030 of the 1,378 files.What the other repositories do
I read the caching rules in the web.config files of the IgniteUI and Infragistics repositories.
_frameworkimmutable. That's correct there only because it is a .NET 10 app; on .NET 9,dotnet.jsandblazor.boot.jsonhave no fingerprint.wwwroot/staticwebapp.config.json, marks all ofpackage_*immutable, includinguno-config.js(Uno.Wasm.Bootstrap issues #1076 and #1090). This PR doesn't follow it.Verified locally
I used IIS Express, configured to answer local requests like remote ones (custom error pages).
Cache-Control.uno-config.js:uno-config.js(1,589 B) from its disk cache without asking the server.dotnet.jsandblazor.boot.json, and loaded the one-year files (bootstrap scripts, runtime, fonts) from disk without a request.What doesn't change
cache: 'no-cache', so they are revalidated on every start whatever the headers say.Related PRs
web.config, so whichever merges second needs a conflict resolved; I'll update Keep the gzip copy of dotnet.native.wasm #19 after this merges. Keep the gzip copy of dotnet.native.wasm #19 already gives itsGzip encodingrule the same status check this PR adds for Brotli.uno-config.jsnames the fingerprinteddotnet.<hash>.js, so a stale copy points at a file the deploy deleted and the app doesn't start. Merge this PR first. The same rule then givesdotnet.<hash>.jsthe one-year policy, which is right because its name changes with its content.web.config. This branch is merged with vnext after Ship only Brotli copies of the WebAssembly site #14, and I re-ran the header matrix on the merged file: every response still has the intendedCache-Control.service-worker.jsgetsno-cache, which helps the retiring worker reach returning visitors quickly.Checking after the deploy
Expected, in order:
no-cache,no-cache,no-cache,public, max-age=31536000, immutable,no-store. The_framework/dotnet.jsline holds for .NET 9 only: on .NET 10 (#18) that file isdotnet.<hash>.js, which gets the one-year policy, anddotnet.jsreturns 404 withno-store.🤖 Generated with Claude Code