Open lokitech opened 7 months ago
@lokitech ... I think this is going to end up being by-design behavior. We've tried (and possibly failed 🙈) to address this situation at (second paragraph) ...
... focusing on ...
Auto mode prefers to select a render mode that matches the render mode of existing interactive components.
Mackinnion's remarks are here ...
https://github.com/dotnet/aspnetcore/issues/52740#issuecomment-1852841365
I'll work that text further based on additional discussion here with the engineers. One of things that I'd like to flesh out in this scenario is exactly when does the router switch over to CSR ... what has to happen to break out of interactive SSR when navigating around Interactive Auto components that have initially adopted interactive SSR.
Hi hello there, thank you for your reply. I would just like to say that I'm a bit perplexed with this decision, consider the following scenario:
Developer creates a Blazor Web App with render mode set to auto and interactivity location to global, meaning essentialy every page and compnent will have the render mode set to auto. First time users, will more than likely, be presented with server-side rendering while the WASM application downloads in the background, so their entirety of that first visit will be server-side rendered since:
Auto mode prefers to select a render mode that matches the render mode of existing interactive components
and auto mode is global. So in this case, only first time visitors and those whose cache has expired will be presented with server-side rendering, while others will always be using client-side rendering (considering there are no new updates published). Correct me if I'm wrong, but this seems to be an overhead of having a Blazor Server for both developing and maintenance for a miniscule return.
What I have measured is that initial load with server-side rendering is faster regardless WASM is cached or not. It would be ideal if every visit to the page is server-side rendered and then switched to client-side rendering as user navigates thourgh the application. I see the problem with application state not being passed to the client from server, but it is neither passed when navigating from interactive auto server-side rendered page to static server-side rendered page and back to interactive auto now client-side rendered page (counter -> home -> counter in my example in the first post). Am I missing something here?
Hi @lokitech,
Consider the following scenario: Developer creates a Blazor Web App with render mode set to auto and interactivity location to global, meaning essentially every page and component will have the render mode set to auto. First time users, will more than likely, be presented with server-side rendering while the WASM application downloads in the background, so their entirety of that first visit will be server-side rendered...
Please correct me if I'm wrong, but I think your argument can be summarized by saying that since navigating from one InteractiveAuto
page to another InteractiveAuto
page results in an entirely new set of components, it's an ideal time to terminate the circuit and start using WebAssembly interactivity, because no component state will be lost. If that's what you're saying, then it should be noted that the "global interactivity" scenario is not equivalent to giving each page an InteractiveAuto
render mode. Global interactivity works by making the router itself interactive, so there's never a transitional period during navigation where the set of interactive components completely changes (because it's the same interactive <Router />
component instance rendering each page). If we wanted to adopt the behavior you're describing for the global interactivity case, we'd have to allow InteractiveAuto
components to dynamically change which interactive runtime they're using (so that the <Router />
can do this), which comes with other challenges that I think distract from the main issue here. Therefore, I'm going to continue by assuming that we're talking about an app with per-page interactivity, where multiple pages are configured to use the InteractiveAuto
render mode. I hope that's a fine assumption to make and that I'm not missing another point you were making.
You're definitely right that there are cases where terminating the circuit and switching to WebAssembly interactivity is worthwhile, even if it means interactive state is lost. However, that's not always going to be the right choice, because the circuit might contain additional state that isn't strictly component state (DI services, etc.) that the app author wants to persist between navigations. You do bring up a good point that navigating to a non-interactive page terminates the circuit and loses interactive state anyway. We felt that it was worth it to dispose the circuit and its state if there aren't any interactive components around to immediately utilize that state, although I can appreciate that it's somewhat subjective to draw the line there.
Perhaps https://github.com/dotnet/aspnetcore/issues/48756 would allow the configuration of some of this behavior, or we could consider another way to allow explicit configuration of what happens when:
InteractiveAuto
components, andInteractiveAuto
component definitely does not correlate with an existing interactive componentIf all these conditions are met, then we could consider terminating the circuit and allowing the InteractiveAuto
render mode to resolve to WebAssembly.
Hello @MackinnonBuck
First off, thank you for your in-depth reply. Indeed I made a mistake by saying "global interactivity" translates to giving each page InteractiveAuto
render mode. I was trying to make a point you summarized perfectly in the first paragraph.
As I've stated I understand the loss of component state along with DI services and everything in the application we are switching from. IMO that's even more of a reason to allow developers greater control over when the switch happens, so we (users-developers) can plan accordingly and tailor it for our use-cases.
I appreciate your time investigating this and considiring it for upcoming releases. Keep up the good work! Karlo
Is there an existing issue for this?
Describe the bug
When using the default Blazor Web App template with interactivity set to auto and per page/component, first time visiting Counter page results in the page being rendered as InteractiveServer which is completely fine, after navigating to Home or to Weather page and then back to Counter, it is rendered in InteractiveWasm which is also great.
The problem occurs when I transfer the Weather page to Client project and set it to InteractiveAuto. After running the application and navigating to Counter or Weather page, the initial load happens in InteractiveServer which is also fine, but no matter how many times I navigate between Counter and Weather pages, it never makes a switch to InteractiveWasm as it does in the case when I navigate to Home and then back to Counter.
Expected Behavior
I would expect that after the WASM files are downloaded, the application would make a switch to InteractiveWasm when navigating between InteractiveAuto pages. As it does when I navigate from Counter to Home and back to Counter.
When navigating from Counter to Home a POST request is made to https://localhost/_blazor/disconnect with circuitId as payload which disconnects the WebSocket.
So when navigating back to the Counter page a GET request is made for blazor-hotreload.js which apparently switches the application from InteractiveServer to InteractiveWasm.
![image](https://github.com/dotnet/aspnetcore/assets/24671023/e02dd9cb-e609-4f88-b74a-aa4b0bd5117c)
So as far I can see, the functionality is there, is there a way to force the switch to InteractiveWasm when navigating from one InteractiveAuto to another InteractiveAuto page after the WASM files are downloaded?
Steps To Reproduce
@rendermode InteractiveAuto
.@code { private string _renderMode = "Static server-side rendering";
}