Description
History
Serving files in ASP.NET Core following production best practices requires a significant amount of work and technical expertise. This usually means that users end up delivering files to the browser in a suboptimal way in their app, even though, for the majority of cases, files are known during the build/publish process and don't change dynamically.This includes optimizations like compression, caching, fingerprinting, and more.
As a result of this, the browser is forced to do additional requests on every page load, more bytes get transferred through the network, and in some cases, even stale versions get served to customers.
Goals
- Serving a given asset once until it changes or the browser clears its cache.
- Preclude the browser from using old or stale assets after an app has updated.
- Preclude the browser from using old asset versions during development.
- Speed up page load times by delivering assets faster using modern browser features.
- Minimize the size of assets served to the browser.
Non goals
- JS minification, CSS minification, and other similar transformations.
Details
We will serve compressed versions for all the assets in your app that benefit from compression, and not just Blazor files. This includes JS, CSS, etc. and any file except for those that are already compressed, like png, jpg, woff, etc.
We will fingerprint all the assets at build time with a hash of the content. This will make the file name unique based on its contents, which will prevent old versions from being reused in lieu of newer versions even if the app has cached the old version.
We will set up caching headers for all the assets that are known at build time. This will make the browser cache the assets for a long time, and only request them again if they change or the browser clears its cache. Fingerprinted assets will be cached using the immutable
directive, which will make the browser never request them again until they change, and we will also include a max-age
directive to the same effect for browsers that don't support immutable
.
We will set up the content-hash as the ETag for all the assets. This will make sure that even if we don't fingerprint a given asset, the browser will be forced to check and download a newer version.
We will provide a map between the assets that aren't fingerprinted and the assets that are that can be used at runtime to find the fingerprinted version of a given asset. This will allow the app to use the fingerprinted version of an asset for files that are automatically generated, like our CSS, and the non-fingerprinted version in the code, like in Razor pages and similar.
This can be use to produce an import map for the app, which will allow the imports in JS files to use the non fingerprinted names, and the browser will automatically use the fingerprinted version. It can also be used to for example, generate link tags in the head of the page to preload the assets without waiting for the browser to discover them.
- [Static web assets] Define static web asset endpoints in the SDK and generate an endpoints manifest #54873
- [Static Web Assets] Define mechanism to fingerprint an asset relative path and generate new endpoints for it. #54874
- [Static Web Assets] Runtime APIs to consume the generated endpoint manifest from the SDK #54875