Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[browser] Cache identity per query string #85775

Open
pavelsavara opened this issue May 4, 2023 · 17 comments
Open

[browser] Cache identity per query string #85775

pavelsavara opened this issue May 4, 2023 · 17 comments
Assignees
Labels
arch-wasm WebAssembly architecture area-System.Runtime.InteropServices.JavaScript os-browser Browser variant of arch-wasm
Milestone

Comments

@pavelsavara
Copy link
Member

pavelsavara commented May 4, 2023

The cache in the WebAssemblyResourceLoader and also the memory snapshot creates different cache for each app.
The current logic takes index.html?item=123 out of http://localhost:53504/index.html?item=123 as cache name.

Therefore the cache is not loaded when user arrived from external deep link item=123 or if the same app has multiple html pages.

If we fully migrate to assets hashes in the asset name, we could drop WebAssemblyResourceLoader.
But the problem would stay for memory snapshot.

@maraf suggested that we could generate Application GUID during build. I guess we would put it into the boot.config.json ?

@ghost
Copy link

ghost commented May 4, 2023

Tagging subscribers to 'arch-wasm': @lewing
See info in area-owners.md if you want to be subscribed.

Issue Details

The cache in the WebAssemblyResourceLoader and also the memory snapshot creates different cache for each app.
The current logic takes index.html?item=123 out of http://localhost:53504/index.html?item=123 as cache name.

Therefore the cache is not loaded when user arrived from external deep link item=123 or if the same app has multiple html pages.

If we fully migrate to assets hashes in the asset name, we could drop WebAssemblyResourceLoader.
But the problem would stay for memory snapshot.

@maraf suggested that we could generate Application GUID during build. I guess we would put it into the boot.config.json ?

Author: pavelsavara
Assignees: pavelsavara, maraf
Labels:

arch-wasm, area-System.Runtime.InteropServices.JavaScript

Milestone: 8.0.0

@pavelsavara
Copy link
Member Author

cc @javiercn thoughts ?

@maraf
Copy link
Member

maraf commented May 4, 2023

I believe the cache key could/should be similar to what @pavelsavara implemented for memory snapshot cache - hash of all configuration params + assets hashes

@pavelsavara
Copy link
Member Author

I think we could still do this in net8 after #89435

@pavelsavara
Copy link
Member Author

It may improve situation for dotnet/aspnetcore#41353

@pavelsavara
Copy link
Member Author

I think we are close to be able to drop the custom Cache and use just HTTP cache + names with hash in it.

@maraf
Copy link
Member

maraf commented Jul 24, 2024

I think we are close to be able to drop the custom Cache and use just HTTP cache + names with hash in it.

After the last discussion, this is not the case ATM. Keeping this open

@maraf maraf modified the milestones: 9.0.0, 10.0.0 Jul 24, 2024
@pavelsavara
Copy link
Member Author

We agreed to drop the cache in Net10, what is holding us back now ?

@maraf
Copy link
Member

maraf commented Oct 9, 2024

We agreed to drop the cache in Net10, what is holding us back now ?

The cache is important for blazor standalone scenario (where you don't have hosting server under control).

@pavelsavara pavelsavara removed their assignment Dec 9, 2024
@pavelsavara pavelsavara added the os-browser Browser variant of arch-wasm label Dec 12, 2024
@javiercn
Copy link
Member

javiercn commented Dec 13, 2024

Putting my thoughts here just to reflect the current state of things:

  • We are doing fingerprinting directly at the SDK level. There is some ongoing work by @maraf to address the remaining cases in standalone scenarios by a combination of using a service-worker and rewriting index.html to include an importmap.
  • Blazor web relies on the cache right now to know if webassembly is already cached (and start that), which won't work if we remove the cache. In that scenario, we need to switch the webassembly bits to use an alternative mechanism. One such approach is to use fetch with the option cache: only-if-cached inside a try_catch block.

With this last bit, I think we can effectively rely on the browser HTTP cache and avoid the need for a second cache.

@pavelsavara
Copy link
Member Author

After asset cache is gone, we should also improve the location of cache for interp-pgo.ts, so that it's shared across URLs of the same app.

@pavelsavara
Copy link
Member Author

For the auto interactive we can store some flag after we finished downloading all assets. Possibly indexDB

@onionhammer
Copy link

Rewrite index.html? What about scenarios where you want to package a .net library as an npm package?

@maraf
Copy link
Member

maraf commented Jan 10, 2025

Rewrite index.html? What about scenarios where you want to package a .net library as an npm package?

@onionhammer In those cases there are probably other tools in the consuming pipeline, like webpack. NPM packages typically don't contain fingerprinted assets and fingerprintg/bundling/etc is done by the consumer.

Am I missing something?

@onionhammer
Copy link

onionhammer commented Jan 10, 2025

@maraf more and more, bundlers are able to work with wasm assets, and yes there is some javascript bootstrapping that comes along for the ride when you build a package; the best thing dotnet could do here is bundle the generated assets in a way that javascript bundlers are pretty much all designed to work with - think webpack, bun, vite, deno, etc.

I have a project that I am attempting to get open-sourced that creates a simple interpreted scripting/expression language - like NCalc, but it works both from .NET and the browser.

I had to write a huge vite plugin for our (internal) purposes in order to bootstrap the output of the _framework directory in because the dotnet compiler's output does not provide a good starting point - I fear this direction of trying to generate the html will make things even worse.

I haven't worked on it in 10 months, so I would need to brush up on things a bit to provide a more detailed analysis - but we still rely on this project heavily, and I would like to open source it. This issue just set off some alarm bells.

IMO, the simplest way to improve the cache-bustability is just to name output files with a hash in them

Image

i.e. dotnet.runtime.123feewf.js

Even with my huge vite plugin, it still doesnt cache-bust properly, hence my interest in this issue.

@danroth27 danroth27 added the Priority:3 Work that is nice to have label Jan 13, 2025
@danroth27 danroth27 added Priority:1 Work that is critical for the release, but we could probably ship without and removed Priority:3 Work that is nice to have labels Jan 22, 2025
@maraf
Copy link
Member

maraf commented Jan 23, 2025

@onionhammer I'm sorry for late reply.

There are several things.

  1. Fingeprinting
    Since .NET 9 we can (and by default do) fingerprint all generated assets (dotnet.js, dotnet.wasm, managed dlls). You need to find an entrypoint into the generated assets (_framework folder). This entrypoint is dotnet.js. In standalone mode (either it's blazor or wasmbrowser template), root document is static (index.html) and so there isn't a dynamic way to resolve fingerprint for dotnet.js and because of that the dotnet.js remains not fingerprinted. That obviously causes caching issues. What we plan to do for this scenario is to write an importmap into the index.html during build and all the assets can be fingerprinted.

  2. Be friendly with bundlers
    The loading process is currently driven by boot.json which tells dotnet.js what needs to be loaded in order to start .NET app. This is specific for .NET. Because of that, we don't recommend bundling .NET build outputs with bundlers. It is currently possible with some custom logic [browser] Is it possible to embed "js-module-native" and "js-module-runtime" JS modules? #89511 (comment). We are looking into changing this json into an ES module (boot.js) that bundlers would understand (related [Blazor] Get rid of Blazor.boot.json and use a different strategy to flow the environment. aspnetcore#59456).

For integration with bundlers (and/or distribution as npm package), I would assume that fingerprinting on .NET side would be turned off and the javascript bundler would do the work of combining/splitting/fingerprinting/etc with the rest of the JS app. Is that assumption correct?

Anyway, this issue is just about custom cache that we currently have and whether fingerprinting can make it obsolete/removed.

@onionhammer
Copy link

onionhammer commented Feb 10, 2025

This entrypoint is dotnet.js. In standalone mode (either it's blazor or wasmbrowser template), root document is static (index.html) and so there isn't a dynamic way to resolve fingerprint for dotnet.js and because of that the dotnet.js remains not fingerprinted. That obviously causes caching issues. What we plan to do for this scenario is to write an importmap into the index.html during build and all the assets can be fingerprinted.

IMO the best approach would just to be to have a build flag that can be set on the compiler, and perhaps also minify/obfuscation preferences, which just switches everything over to generate normal bundler friendly ES module code rather than obfuscated/minified... whatever is going on inside of dotnet.js

I would assume that fingerprinting on .NET side would be turned off and the javascript bundler would do the work of combining/splitting/fingerprinting/etc with the rest of the JS app. Is that assumption correct?

Yes, thats the best case scenario, if you could import the library generated directly into something like node/vite/rollup/bun/deno etc. Some of these may have different ways of handling wasm.

I just upgraded my project to .net 9 to play with it, and it is indeed an improvement to have the filenames hashed (other than blazor.boot.json), so I'm also subscribing to the #blaazorboo issue.

@lewing lewing removed the Priority:1 Work that is critical for the release, but we could probably ship without label Feb 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
arch-wasm WebAssembly architecture area-System.Runtime.InteropServices.JavaScript os-browser Browser variant of arch-wasm
Projects
None yet
Development

No branches or pull requests

6 participants