Environments + client services w/prerendering#31057
Conversation
MackinnonBuck
left a comment
There was a problem hiding this comment.
Looks like a great start - I have some ideas and thoughts!
Co-authored-by: Mackinnon Buck <mackinnon.buck@gmail.com>
|
@MackinnonBuck ... I think I have most of the 🦖 RexHacks!™ 🦖 out of the PR. 🙈 |
|
... and I changed the section name in the Environments topic ... - Read the client-side environment in a Blazor Web App
+ Read the environment in a Blazor Web App... because the environment is being read in both and this has broader implications because it also applies to Auto components. UPDATE: I added a couple of more commits 👇, and I think I'm good now. |
MackinnonBuck
left a comment
There was a problem hiding this comment.
Looking good! I do also want to hear an opinion from @javiercn or @SteveSandersonMS before we officially suggest this approach to customers.
|
@MackinnonBuck ... Looks good, but can we use |
That sounds fine to me! 🙂 |
|
|
||
| This error occurs because the component must compile and execute on the server during prerendering, but <xref:Microsoft.AspNetCore.Components.WebAssembly.Hosting.IWebAssemblyHostEnvironment> isn't a registered service on the server. | ||
|
|
||
| There are a four approaches that you can take to address this scenario. The following are listed from most recommended to least recommended: |
There was a problem hiding this comment.
Often a simpler option is to inject IServiceProvider instead of the service type itself, and then you can have code like:
if (Services.GetService<IWebAssemblyHostEnvironment>() is {} env)
{
// ... do stuff with env
}TBH that seems easier than making a new abstraction.
There was a problem hiding this comment.
AH! I see ... yes ... BUT, it won't resolve an environment at all during prerendering. If the dev is counting on the value there, this will 💥 break their logic, correct?
It looks like this would be good for only Interactive WebAssembly rendering without a prerendering value required when it executes.
UPDATE: This was @MackinnonBuck's second bullet. I've placed this guidance on the PR above the list as a solution for when the value isn't required during prerendering.
|
@guardrex @MackinnonBuck Could you clarify which specific part of this doc is the "approach" that you consider at risk of being controversial, and are asking for feedback about? I've read through it and nothing instantly springs out as being problematic, but it is a long doc and maybe I've missed something. |
|
Oh wait, I think I see now. You're referring to the stuff about While this approach would certainly work, it has the drawback that it doesn't create compatibility with existing code that already depends on accessing Implement IWebAssemblyHostEnvironment on the serverYou may have considered this, not sure, but why not simply create your own service implementation for public class ServerHostEnvironment(IWebHostEnvironment env, NavigationManager nav) : IWebAssemblyHostEnvironment
{
public string Environment => env.EnvironmentName;
public string BaseAddress => nav.BaseUri;
}... with Fix it in the frameworkLonger term, if this is a common pain point, we could change the framework code that registers the WebAssembly hosting endpoints etc so that it also registers an implementation of |
|
|
||
| ## Apply a render mode to the entire app | ||
|
|
||
| To set the render mode for the entire app, indicate the render mode at the highest-level interactive component in the app's component hierarchy that isn't a root component. |
There was a problem hiding this comment.
A concrete example here will be good. It's impossible for anyone without context to understand what is being said here. (To give you an idea, I have context and I had to stop to think about it).
There was a problem hiding this comment.
The definition of a render mode and how to set it for component instances and component definitions were just explained in the preceding sections. What's not clear?
There was a problem hiding this comment.
I did not go through the previous section. Let me read through it
I like it, but I recommend keeping the service-based approach listed in case it has utility in other cases. One thing tho ... is |
| > [!NOTE] | ||
| > Making a root component interactive, such as the `App` component, isn't supported because the Blazor script may be evaluated multiple times. Therefore, the render mode for the entire app can't be set directly by the `App` component. |
There was a problem hiding this comment.
I don't think the Blazor script evaluating multiple times was the issue here. I don't remember the exact details
There was a problem hiding this comment.
This appears in a few other spots. I'll fix it everywhere on this PR later.
There was a problem hiding this comment.
In my recollection, it was that the script was being evaluated multiple times.
Nonetheless we don't have to explain why it's unsupported for the root component to be interactive. We only need to communicate that it is unsupported.
There was a problem hiding this comment.
I fixed it by removing the reason.
|
@SteveSandersonMS ... I placed your approach as the top pick. I just moved the concept of custom services down to the second spot in the list, and it won't have an example in the docs. In the Environments article, I placed the full example that you provided. |
Yeah I probably did mean TryAddScoped. Sorry. I was just typing from memory and haven't verified that the code is correct and would compile. |
|
I added the @MackinnonBuck, your bullet number 2 was @SteveSandersonMS's idea in code form. I removed that bullet from the list given that I'm moving it up above the list. I also moved your last bullet on disabling prerendering to just under the The list is meant to include only the approaches that fully solve the problem, which is to obtain the value during prerendering. I think the list has the three good approaches. I recommend re-reviewing the entire section along with the new example in the Environments doc. |
Co-authored-by: Javier Calvarro Nelson <jacalvar@microsoft.com>
|
Going ahead with this. If there's additional feedback, I can create a new PR. |
Fixes #31025
Addresses #28161
Mackinnon ... I decided to draft this with a full explanation and examples for what's going on with client-side services in a BWA. It's a little long. However, I can understand it this way, so we have a good bet on not losing anyone.
In the Render Modes article, the Set the render mode for the entire app section was too far down the article. I moved the section up and changed the heading name to Apply a render mode to the entire app. The new section on Client-side services fail to resolve during prerendering makes reference to globally setting the render mode. I want to reader to have already seen that section.
Internal previews