dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
34.59k stars 9.79k forks source link

Full stack web UI with Blazor #46636

Closed danroth27 closed 8 months ago

danroth27 commented 1 year ago

In ASP.NET Core today, we have a couple of different ways to build web UI:

  1. MVC & Razor Pages: These frameworks use server-side rendering (SSR) to dynamically generate HTML from the server in response to requests. Rendering from the server helps apps to load fast šŸš€ because all of the hard work of fetching the data and deciding how to display it has already been done on the server - the client just has to display the already rendered HTML. They can take advantage of powerful server hardware and directly access backend data and services.
  2. Blazor: Blazor's component model is focused on handling UI interactions from the client. Server-side rendering requires every UI interaction be sent to the server, so it isn't great for richly interactive UI. For rich interactivity šŸŽ® you want to use client-side rendering (CSR), which has much lower latency and can readily access client capabilities.

Many modern web apps need to use a combination of these approaches, both server-side rendering and client-side rendering. Maybe your home page or blog is best handled with server-side rendering so that it loads fast and is easily indexed, while the more elaborate functionality of your app needs the responsiveness of running from the client. Currently, with .NET, this requires using multiple different frameworks together: MVC, Razor Pages, and Blazor.

This issue proposes to combine the benefits of server-side and client-side rendering into a single consistent model based on Blazor , that we're currently calling Blazor United (name subject to change). Blazor in .NET 8 will enable you to use a single Blazor-based architecture for all your web UI scenarios. You can use Blazor components to render HTML directly from the server and also enable full client-side interactivity with Blazor Server or WebAssembly. That's all within a single project with the ability to easily switch between different rendering modes and even mix them in the same page. Blazor in .NET 8 will also enable new rendering capabilities like streaming rendering and progressive enhancement of navigations and form posts.

@SteveSandersonMS put together a video of an early prototype that demonstrates many of the intended capabilities.

Related issues:

mammadkoma commented 1 year ago

If we use MudBlazor components and then use RenderMode.Auto, it loads first the page server side then after download the MudBlazor components and other wasm dll load and work on client side browser? We only want to increase the startup speed.

chrissainty commented 1 year ago

What will the programming experience be when authoring components? Will we need platform checks to decide if were running on WASM or Server and then decide to call an API or a local service?

ahazelwood commented 1 year ago

Blazor United brings a lot of functionality to a table, but I'm curious how it will handle the following scenarios:

  1. RenderMode.Auto is used and for some reason the Websocket connection is cancelled because of a new build deployment. Will the data the client sees survive this? Or will the user have to re-enter any data they may have provided? (This assumes no major changes to the underlying parameters).
  2. If I update a Razor component, will it be smart enough to only download the changed assembly and not the entire wasm framework on a new deployment?
marcoatribeiro commented 1 year ago

How will HttpContext be handled by Blazor United, as it is available in Blazor Wasm but not in Blazor Server?

danroth27 commented 1 year ago

If we use MudBlazor components and then use RenderMode.Auto, it loads first the page server side then after download the MudBlazor components and other wasm dll load and work on client side browser? We only want to increase the startup speed.

@mammadkoma With the Auto render mode the app loads first using Blazor Server. The .NET WebAssembly runtime is downloaded in the background and cached so that it can be used on subsequent navigations to that page. The idea is to ensure the app always loads fast while pushing load off of the server as soon as possible.

danroth27 commented 1 year ago

What will the programming experience be when authoring components? Will we need platform checks to decide if were running on WASM or Server and then decide to call an API or a local service?

@chrissainty The expectation is that the vast majority of components should be authored to function with all rendering modes. Otherwise, you dilute the value of component reusability! But we do want to enable scenarios where you need to platform specific things. That's where the normal .NET tricks of using cross-compilation and runtime checks come in to play.

mammadkoma commented 1 year ago

If we use MudBlazor components and then use RenderMode.Auto, it loads first the page server side then after download the MudBlazor components and other wasm dll load and work on client side browser? We only want to increase the startup speed.

@mammadkoma With the Auto render mode the app loads first using Blazor Server. The .NET WebAssembly runtime is downloaded in the background and cached so that it can be used on subsequent navigations to that page. The idea is to ensure the app always loads fast while pushing load off of the server as soon as possible.

So we can use MudBlazor wasm components. But what about if the user doesn't change the page? All requests are blazor server mode until the user change the navigation? Or after the dlls are downloaded in background the wasm mode work?

danroth27 commented 1 year ago

How will HttpContext be handled by Blazor United, as it is available in Blazor Wasm but not in Blazor Server?

@marcoatribeiro Great question. I don't think we have a clear answer for this yet. The related work is tracked by #46393. Proposals on how you think should work are welcome!

danroth27 commented 1 year ago

So we can use MudBlazor wasm components. But what about if the user doesn't change the page? All requests are blazor server mode until the user change the navigation? Or after the dlls are downloaded in background the wasm mode work?

@mammadkoma Right, the page would continue to use Blazor Server initially and would only transition to use Blazor WebAssembly on a subsequent page load. This avoids a bunch of complexity with trying to transition from Blazor Server to Blazor WebAssembly while the page is still active. It does mean that if the user stays on the page for a long time the circuit might be long lived.

mihaimyh commented 1 year ago

What about dlls being blocked by some antiviruses, even renaming the extension from .dll to something else doesn't help. This will make the transition to Wasm impossible.

bub-bl commented 1 year ago

Before we start, very good work! I appreciate the work you provide for the .NET platform. I have a question related to rendering. Let's say I have a page that is rendered by WebAssembly, in this page I have a component that is rendered by the server, can I share data with the components that do not share the same rendering mode? Are the cascaded values still functional even if the parent and child don't share the same rendering mode?

danroth27 commented 1 year ago

What about dlls being blocked by some antiviruses, even renaming the extension from .dll to something else doesn't help. This will make the transition to Wasm impossible.

@mihaimyh See https://github.com/dotnet/runtime/issues/80807 for our effort to address this.

gerneio commented 1 year ago

Regarding naming, while I do like Blazor United, as @danroth27 kind of eluded to in that latest community stand up (link to YT timestamp), perhaps "Blazor Web" is more appropriate to avoid confusion with Blazor MAUI/Hybrid. Kind of a toss up. šŸ¤·ā€ā™‚ļø

Only other thing I wanted to add was that we probably should be thinking about what sort of code analyzers can be added so that if we render a SSR-only component and don't have stream rendering enabled for a particular component that requires it to function properly, then from VS we can show some warnings that the coded behavior may differ from the actual runtime behavior (or can be optimized by enabling stream rendering). And a similar analyzer would also apply to when we are using a component that ties to Blazor WASM/Server specific interactivity (i.e. button clicks) when we're not using Server, WASM, or Auto render modes.

I have no clue on what would be the best way to implement such an analyzer, but I think you'd want the warning to be shown where the component is being consumed IF the render mode is specified inline (i.e. <MyComponent rendemode=server />), otherwise show it within the component itself if the rendermode attribute is specified in its .razor file. Might have to walk the tree of consumed components to determine the render mode of a N-level nested component. Would need to be mindful of components coming from RCL's & 3rd party component vendors.

ChristopherHaws commented 1 year ago

Amazing work guys! Love all the new stuff coming out :)

I feel like the name should just be Blazor SSR (server-side rendering). This is what other front-end frameworks call it when the app is rendered on the server, sent to the client, and then the client hydrates the SPA to allow for a seamless transition. I see no reason to make up a new name. ^_^

krzychacz1 commented 1 year ago

Will RenderMode.Auto detect that user is using an old browser (without support webassembly) and will keep ServerMode (no switch to webassembly) ?

SteveSandersonMS commented 1 year ago

So we can use MudBlazor wasm components. But what about if the user doesn't change the page? All requests are blazor server mode until the user change the navigation? Or after the dlls are downloaded in background the wasm mode work?

As things stand, it's likely we'd only start newly-added component instances on WebAssembly, and leave existing Server components running until they go away naturally (e.g., when a user navigates to a different page). Migrating a running component instance would require your application to transfer its live state from server to client, and that would introduce many more difficulties for the application developer. You'd have to guarantee that all state is serializable (which is not the default in .NET) and you never reference large chunks of data, and you'd have to guarantee the user doesn't change the state while it's being transferred, and there's never any data you forgot to include, and so many other things. You probably don't want to deal with all that except in extreme cases, given the alternative is just waiting for the user to navigate (easy) or prompting them to let you refresh the page (also easy).

What will the programming experience be when authoring components? Will we need platform checks to decide if were running on WASM or Server and then decide to call an API or a local service?

That's a great question and one we've spent some time thinking about. In the BestForYou demo, we had an interface abstracting over the "save recipe" operation, with a server implementation that hits EF directly and a wasm implementation that calls a minimal API. For .NET 8 this sort of "abstract it yourself" approach might be where we land, but longer term we're considering ways to automate the creation of the abstraction at compile time. The challenges are with things like auth, logging, or other cross-cutting concerns: when the call comes from an external untrusted client, you actually want to handle it differently than when the call comes from trusted server-side code. If the abstraction is too powerful and too automatic, developers will be prone to forgetting they are exposing sensitive server-side operations to untrusted clients, so careful design is needed.

RenderMode.Auto is used and for some reason the Websocket connection is cancelled because of a new build deployment. Will the data the client sees survive this? Or will the user have to re-enter any data they may have provided? (This assumes no major changes to the underlying parameters).

One of the advantages of Blazor United is that it encourages an architecture where as many pages as possible are stateless and don't even involve a circuit, so a large percentage of your users are indifferent to changes of server. However, when a component is running interactively on the server, you should assume it has the same behaviors as Blazor Server today. There isn't automatically some new way to preserve state across server restarts (see all the commentary about serialization etc above). We could introduce manual ways to persist selected pieces of data, but all the responsibility for actually doing that and providing a backing store would still fall on the app developer.

If I update a Razor component, will it be smart enough to only download the changed assembly and not the entire wasm framework on a new deployment?

When a component is running interactively on WebAssembly, you should assume it has the same behaviors as Blazor WebAssembly today. We already have a caching system that causes the client to only fetch files it doesn't already have cached locally (so if some framework library is already cached, it doesn't refetch the same version of that file).

How will HttpContext be handled by Blazor United, as it is available in Blazor Wasm but not in Blazor Server?

When doing passive SSR, we expect to provide ways of accessing all the data you need from the request/response, but haven't confirmed the API shapes yet. Hopefully we will not expose HttpContext directly as that would lead to inconsistencies across platforms (note that HttpContext is not available in WebAssembly because there's no request/response).

What about dlls being blocked by some antiviruses, even renaming the extension from .dll to something else doesn't help. This will make the transition to Wasm impossible.

That's not specific to anything in Blazor United, but as it happens we do have work ongoing to address that. For further discussion please see https://github.com/dotnet/runtime/pull/79416

Regarding naming

If you don't mind, I'm going to ignore any naming discussions - it not in the scope of what's being planned/investigated here.

I have a question related to rendering. Let's say I have a page that is rendered by WebAssembly, in this page I have a component that is rendered by the server, can I share data with the components that do not share the same rendering mode? Are the cascaded values still functional even if the parent and child don't share the same rendering mode?

It's not fully prototyped yet (we've done it but only partially). The expectation is that you should be able to nest passive/server/client components in any combination. When there's a seam between different rendering modes, any parameters have to be serialized of course. Support for RenderFragment parameters may be limited and callbacks (e.g., for events) may not be possible across seams, at least not initially. One design challenge in this area is that the scenarios aren't totally clear - the idea of passive->client->server->passive->client nesting exists in theory but in practice who would ever do this and why? What specific scenarios would guide prioritisation for what features would be important to make cross seams?

And a similar analyzer would also apply to when we are using a component that ties to Blazor WASM/Server specific interactivity (i.e. button clicks) when we're not using Server, WASM, or Auto render modes. ... Might have to walk the tree of consumed components to determine the render mode of a N-level nested component.

You're right that this is potentially useful but also that it's potentially difficult, given the fact that components themselves are usually agnostic to render mode, can have dynamically chosen children, and we would have to know about all descendant components transitively. Runtime checks are far more straightforwards for this kind of thing. For compile-time checks, it's totally possible we might be able to provide some helpful hints, but it's nontrivial to solve in general.

Will RenderMode.Auto detect that user is using an old browser (without support webassembly) and will keep ServerMode (no switch to webassembly) ?

Interesting idea. TBH, throughout the lifetime of Blazor WebAssembly, we've had little to no feedback that people are troubled by very old browsers that don't support WebAssembly. That's a very niche scenario at this point. However it would be really simple for us to include that rule in the client-side logic that resolves Auto to a specific render mode!

gerneio commented 1 year ago

So one thing that was demo'd was the ability to enable Auto mode and the browser will first establish a signal-R connection for a "Blazor Server"-like interaction, and then silently download the WASM runtime and corresponding DLL's to then switch to "Blazor WASM"-like interaction on next page load. However, unless I missed something, if I first load a SSR page, then neither of the above operations occur, is that correct? What would be nice would be the option to opt-in to when loading a SSR page, to also silently begin downloading the WASM runtime and DLL's. The key part being the ability to opt-in/out of this "WASM pre-fetch" behavior depending on the loaded route. For example:

Scenario 1: (This should be similar to what y'all demo'd I think)

I have a SSR (probably w/ streaming) product listing page as my "landing page" with no Blazor interactivity needed (i.e. button event clicks), just pure navigation (show a list of pictures, pricing, and a linked anchor tag to get to a product detail page). When I open the product page is when I need some Blazor interactivity (i.e. button event clicks).

In this scenario (again based on y'alls demo), if Auto render mode was enabled, the product listing page (landing page) is rendered with SSR. Once the user navigates to the product detail page THEN a signal-R connection is created and WASM runtime/DLL's are downloaded in the background. However, what would be preferred in this scenario is that on the SSR product listing page, having the WASM dependencies download already initiated in the background, therefore avoiding the signal-R connection all together (unless the user navigates that fast or connection is that slow).

So in summary, in this scenario, I would want all the WASM dependencies to be downloaded in the background of my SSR landing page. Having the ability to opt-in to this "WASM pre-fetch" feature would be preferred in this example.

Scenario 2:

I have a SSR login page as my "landing page" with no Blazor interactivity needed (i.e. button event clicks). I use typical form submission to POST to the server. On successful login, the server responds with a auth cookie and a redirect to the user's profile page, which does require Blazor interactivity (i.e. button event clicks).

In this scenario, if Auto render mode was enabled, the login page is rendered with SSR. Once the user authenticates and the browser redirects to the profile page THEN a signal-R connection is created and the WASM runtime/DLL's are downloaded in the background. In this scenario, the default behavior (assuming I understood it correctly from the demo) is exactly what would be preferred, the goal being don't download any WASM dependencies until we have an authenticated session. This wouldn't necessarily be for security reasons since any DLL downloaded to the browser at any point should be considered insecure, however this would be more along the lines of "trying" to ONLY allow our software to be obtained by authenticated user's (i.e. a customer who has paid for our software and therefore is allowed to download the software package).

So in summary, in this scenario, I would NOT want any WASM dependencies to be downloaded in the background of my SSR landing page, but rather wait until an authenticated navigation has occurred. Having the ability to opt-out of this "WASM pre-fetch" feature would be preferred in this example.

Hope this makes sense. The end goal would be to have the ability to opt-in/out of pre-fetching WASM dependencies from a SSR landing page while still using the Auto render mode.

RyoukoKonpaku commented 1 year ago

@gerneio yeah, I'd love for this scenario as well where I can basically pre-fetch the wasm runtime on the SSR pages so it's already ready the moment you navigate to a page that needs it, ideally from a service worker (so it doesn't get cancelled between browser nagivations). Maybe from an attribute so I can control which route initiates the wasm pre-fetch.

gmurray81 commented 1 year ago

@SteveSandersonMS I'm not sure if this has been discussed somewhere already, but it would be super useful if a Component could say "my only supported mode is client". I could drill into this in a lot of depth if you'd like, but the short version is that this would be exceptionally useful.

Ponant commented 1 year ago

I hope blazor united will setup a clear path to auth, and in particular it seems it will be well suited to a BFF type security setup (cookies sent from the fornt end to a dedicated server).

Ponant commented 1 year ago

I really think that given the shift in the auth specs that it is wise to target BFF back-end-front-end strucutures with cookies.

simonziegler commented 1 year ago

@SteveSandersonMS thanks for the expanatory thread above. I have a couple of questions/observations:

Seams - you mention that there may be issues with callbacks across seams. My interest here is for component libraries (there's been some mention of MudBlazor above and I'm an author of Material.Blazor). It makes a lot of sense for component libraries to use the Auto mode, especially if they make use of JS Interop, thereby minimising latency. Some Material.Blazor components use callbacks to facilitate back end/database functionality to feed datasets to components. It would therefore be great for Auto or WASM rendered components to have the ability to issue callbacks across a seam into their server rendered app.

Static hosting - If I have a WASM static hosted app, will components libraries with render mode of "auto" still work? If not how should one approach this? Either (i) will an RCL consumer have the ability to specify the render mode for an entire library (specifying this at compile time rather than run time feels most natural), or (ii) will the RCL need to be published in multiple variants, i.e. WASM variant, Auto variant etc?

Blazor United is a stunning prototype and will dramatically improve my business's app. Thank you.

SteveSandersonMS commented 1 year ago

@simonziegler I would generally expect RCLs not to declare a specific render mode. That's the default and is the situation already for all existing RCLs. The application developer consuming a component from an RCL will either (1) specify a render mode at the location where they use that component, or (2) allow the component instance to inherit the render mode that's already in effect at that location.

I don't think RCL authors will generally want to specify a render mode because they have no way to know what render modes the hosting application will want to support. We are letting app developers choose whether their app supports Server, WebAssembly, both, or neither (i.e., passive SSR only), and there are legit cases for all four of these combinations.

I know people will say they want to indicate that a component "requires" interactive rendering but we may yet find it's better to leave the app developer in control of that. There are legit cases for passively rendering anything, even components whose full functionality only takes effect with interactive rendering. We can allow app developers to make that choice, especially if it's clear and obvious to them what choice they are making.

Static hosting - If I have a WASM static hosted app, will components libraries with render mode of "auto" still work?

Again, I don't think the RCL component should generally specify any render mode. But the answer to your question is yes. If a component is being used in an interactive context - Server or WebAssembly (including a statically-hosted wasm app) - then specifying the "auto" render mode has no effect since the component will just be rendered in the enclosing Server/WebAssembly context.

simonziegler commented 1 year ago

@SteveSandersonMS that makes sense and I can see that an RCL should be agnostic to its render mode. One thing I would like as an app developer/RCL consumer though is to say "the default for this RCL, or namespace maybe is Auto/WASM etc" so that I don't need to specify this on each and every component (of which I have thousands). Is this something that might be manageable?

gmurray81 commented 1 year ago

@SteveSandersonMS I'd encourage you to consider letting a component force it's rendering mode to client at least, not necessarily forcing to server, even if it drives WASM being required.

Needing to support server mode makes certain classes of components really onerous to produce and maintain for Blazor. The problem of interactivity and latency can be addressed by having more of the interaction logic be JavaScript rather than C# (even if this rankles a bit when it could have been WASM) but the really insidious issue is that this JS logic cannot synchronously interact with the C# logic since it may be running on the server.

This forced asynchrony between JS logic and C# logic makes whole classes of problems much more intractable. A scenario that could have been handled imperatively with an event instead MUST be handled declaratively to that it can execute entirely in JS with the rest of the interactive logic.

Instead, if we were able to indicate "this component always runs on the client, and all event handlers, etc, attached to it also run client side (WASM)" this would immediately make Blazor 1000% easier to work with.

I appreciate that this is a significant challenge to implement, but it sounds like you are addressing it if you are considering letting the developer select the rendering mode of a component. But I'd implore you to consider also allowing a component to force it's mode to client.

I understand forcing to server would complicate the hosting on behalf of the consumer of the component, but isn't forcing client mostly complicating the build process?

gmurray81 commented 1 year ago

As it stands, if we are adapting an existing web component to Blazor, for example, we actually need to alter large portions of it's API to have declarative options rather than the simple event based hooks it had originally. And invariably some capability is lost even so, necessitating consumers of the component sometimes needing to provide an event handlers using JS instead of C#. Again, I can go into the challenges the forced asynchrony bridge impose in super fine detail if you'd like. But suffice it to say it would be my favorite Blazor feature ever if you could force all interaction with a component to be client side and able to bridge synchronously.

SteveSandersonMS commented 1 year ago

In the prototype it is already possible for a component to specify a particular default render mode for itself. I was only suggesting that most RCL components shouldn't do that (assuming their goal is to maximise flexibility for the user), even though technically they can.

If a component explicitly demands a render mode that isn't supported on the host, based on what the app developer has configured, that will just result in an error.

gmurray81 commented 1 year ago

@SteveSandersonMS that sounds excellent, actually. What are the scenarios where forcing client wouldn't function? If they have configured their app to be ssr only with no script payloads? Disabled WASM building?

SteveSandersonMS commented 1 year ago

If they have configured their app to be ssr only with no script payloads? Disabled WASM building?

Correct

iam3yal commented 1 year ago

I'm building a UI library on top of Blazor specifically IComponent and ComponentBase, does this mean I should update all of my component to support this new model? it might be too early to comment on breaking changes and how do we migrate into this model but do you guys expect any sort of fundamental changes? I hope you will keep the name Blazor for simplicity and add Blazor United model as an addition and a choice because having to think about Blazor the old and Blazor the new might be confusing.

dazinator commented 1 year ago

@danroth27

If we use MudBlazor components and then use RenderMode.Auto, it loads first the page server side then after download the MudBlazor components and other wasm dll load and work on client side browser? We only want to increase the startup speed.

@mammadkoma With the Auto render mode the app loads first using Blazor Server. The .NET WebAssembly runtime is downloaded in the background and cached so that it can be used on subsequent navigations to that page. The idea is to ensure the app always loads fast while pushing load off of the server as soon as possible.

How about if you publish and serve the blazor wasm app from a CDN (that purely serves up static files for speed of delivery) and the api that the wasm app talks to is your aspnet core api hosted somewhere else - I'm struggling to conceptualise where or if server side pre-rendering or blazor United has any relevance in this model?

SteveSandersonMS commented 1 year ago

does this mean I should update all of my component to support this new model

You should not have to do anything different. If you already support Server and WebAssembly hosting models then your component will already work when rendered in those modes. If you already support prerendering, your component will already work when rendered passively (i.e., SSR only). Of course, things like event handlers only work with interactive rendering so you may consider interactive rendering a prerequisite for your component, depending on what it does.

How about if you publish and serve the blazor wasm app from a CDN (that purely serves up static files for speed of delivery)

In this hosting scenario you're doing exactly what Blazor WebAssembly apps have always done and nothing changes in terms of capabilities or data access. You can't do any server-side rendering if you're hosting on a static-files CDN because you don't have a server that can run your code.

PeterDraex commented 1 year ago

Does Blazor United bring any advantages to a Blazor WASM app that must be indexable by search engines?

SteveSandersonMS commented 1 year ago

It gives you the option to implement parts of your app with pure server-side rendering. For the parts you continue to render interactively with WebAssembly, it's just equivalent to the existing prerendering support.

PeterDraex commented 1 year ago

What are some reasons I might want to implement parts of the app with pure server-side rendering?

Thanks

SteveSandersonMS commented 1 year ago

For general info, I'd recommend web searching for something like "server-side rendering vs client-side rendering". Eventually we'll publish Blazor-specific guidance but it's too early for that right now.

dazinator commented 1 year ago

@SteveSandersonMS

How about if you publish and serve the blazor wasm app from a CDN (that purely serves up static files for speed of delivery)

In this hosting scenario you're doing exactly what Blazor WebAssembly apps have always done and nothing changes in terms of capabilities or data access. You can't do any server-side rendering if you're hosting on a static-files CDN because you don't have a server that can run your code.

Thanks!

Just to explore avenues on this front, suppose you want SSR, and to serve static files up from a CDN predominantly (as downloading these static files can be closer to the user and served up quicker, and not consume app server bandwidth) is there some sort of approach that will allow this i.e initial request hits aspnet core server, it responds with something that causes the browser to download the wasm files from an external CDN somewhere (e.g some custom index.html?) - but once that completes and the spa loads in the browser, the spa's blazor components can still connect back to the aspnet core server again rather than their point of origin (the cdn) in order to use SSR ? I don't think I'd want to go down this road, but there are attractive qualities of being able to offload serving of static files to CDN's, and also attractive qualities of SSR within an app for certain use cases - so it begs a question.

Pinox commented 1 year ago

@dazinator Yup same question from me. Would be useful to keep the SSR "super light" and offload all downloading to a separate CDN. Is this possible ?

SteveSandersonMS commented 1 year ago

That sounds not specific to Blazor United but would be applicable to any Blazor WebAssembly app. If you want to follow up about that, could you post a separate issue? Thanks.

meisam-dehghan commented 1 year ago

one thing I'm curious about is what will happen in Balzor United when a component is rendered as a server-side page(as in Razor Pages now),but a component with the server-side mode is also used as part of the page to add interactivity.Will then the whole page go blank,as is the case currently,if the user doesn't interact with the page for a few minutes?

daniel-p-tech commented 1 year ago

Is the following scenario going to be supported by Blazor United?

Simple HTML landing (marketing) page of a product with a login/register button at the top. As soon as this HTML page is loaded, all WASM resources start downloading and when finished, user will be able to click the two buttons and the corresponding WASM page will be rendered instantaneously.

The landing/marketing page is really just static HTML and I don't want to do any pre-rendering or server side Blazor at all. I watched the introductory video a few days ago and if I remember correctly something like that is being considered?

This particular use case is what I've been looking for since day one.

Thanks!

SteveSandersonMS commented 1 year ago

a component with the server-side mode is also used as part of the page to add interactivity.Will then the whole page go blank,as is the case currently,if the user doesn't interact with the page for a few minutes

I assume you're referring to the situation where a user's websocket connection is lost (which isn't normally caused by a few mins of idleness, but it certainly can happen). We haven't made a design for the connection-lost scenario yet, but by default, it would be the same as Blazor Server's existing handling for this (i.e., a full-screen "reconnecting..." overlay). I'm not sure what else you could do since it would be hard to communicate to a user that some parts of the page are frozen but other parts will work. Technically you can already customize this as much as you want - I'm just talking about the built-in default.

Is the following scenario going to be supported by Blazor United?

Yes, but you can already do that today. Just have your Blazor WebAssembly app's index.html contain all this static HTML you're describing, and that's what will show up until the runtime is downloaded and started (at which point you can render the same UI except now your buttons work).

daniel-p-tech commented 1 year ago

But once the runtime is downloaded isn't the index.html page completely replaced? Wouldn't things like scrolling position etc be lost?

SteveSandersonMS commented 1 year ago

But once the runtime is downloaded isn't the index.html page completely replaced? Wouldn't things like scrolling position etc be lost?

The DOM is completely replaced today, but I don't think that will result in scroll position being lost as long as the new content matches the old. The DOM update is performed synchronously. I just checked that setting document.body.outerHTML = document.body.outerHTML doesn't lose a page's scroll position despite replacing all of the DOM elements.

With Blazor United, we plan to enhance things and retain the original server-rendered DOM elements when performing enhanced navigation and form posts, but we are not planning to retain the original server-rendered DOM elements when activating an interactive component, as this is expensive to implement and leads to other problems with the DOM being out of sync (e.g., if a user has already started typing into a textbox that has a per-keystroke event handler). So I don't think anything specifically will change for the Blazor WebAssembly scenario.

meisam-dehghan commented 1 year ago

We haven't made a design for the connection-lost scenario yet, but by default, it would be the same as Blazor Server's existing handling for this (i.e., a full-screen "reconnecting..." overlay)

Actually, It'd be pretty counter-innovative to stick with the existing handling of Bazor-Server's connection-lost scenario. I think you could make it possible for the developer to set the idle time, and also provide a customizable component to be displayed when the connection is lost. Better yet, It would be awesome if you could write a JavaScript that would automatically reconnect without even the user realizing that the connection was lost as he/she moved the mouse wheel.

nakamacchi commented 1 year ago

@SteveSandersonMS In .NET 8 or later versions, will the project model (in Visual Studio) be changed? i.e., will Blazor Server project and Blazor WebAssmbly project be both remained? Or single unified project system (#46398) would be offered? I think that blazor united is very innovative, but developing Blazor apps which can work both in SSR/CSR mode would require additional efforts and careful development. So it would be happy to keep the Blazor Server project and Blazor WebAssmbly project models.

SteveSandersonMS commented 1 year ago

@nakamacchi That's listed as one of the open questions at https://github.com/dotnet/aspnetcore/issues/46395. If you want to add any feedback about scenarios, that would be a great place for it. Thanks!

rmmcgr commented 1 year ago

The concepts for Blazor United are interesting. I'm trying to understand if/how there will be any possibilities to do something like Turbo Frames, without needing a component (or the whole page) set to server render mode, that in turn would need a WebSocket connection?

That is, within a scoped element, like a div tag, would it be possible to make a HTTP Get request by clicking a link (or enhancing any element to trigger a request in various ways, in the style of Htmx), that updates just the contents of that scoped div or another named element on the page?

TehGM commented 1 year ago

So we can use MudBlazor wasm components. But what about if the user doesn't change the page? All requests are blazor server mode until the user change the navigation? Or after the dlls are downloaded in background the wasm mode work?

As things stand, it's likely we'd only start newly-added component instances on WebAssembly, and leave existing Server components running until they go away naturally (e.g., when a user navigates to a different page). Migrating a running component instance would require your application to transfer its live state from server to client, and that would introduce many more difficulties for the application developer. You'd have to guarantee that all state is serializable (which is not the default in .NET) and you never reference large chunks of data, and you'd have to guarantee the user doesn't change the state while it's being transferred, and there's never any data you forgot to include, and so many other things. You probably don't want to deal with all that except in extreme cases, given the alternative is just waiting for the user to navigate (easy) or prompting them to let you refresh the page (also easy).

This is a little bit disappointing - I definitely hoped that it'd replace the connection altogether. However the reasoning you're giving is understandable. But just to clarify - does it mean that once a new component on the same page is rendered after WASM loads, that specific component will be handled by WASM while older ones will still live on circuit? Or will a full page refresh to reload application be needed?

And as an another question - currently one of issues that Google PageSpeed points out, but also is noticeable on mobile phones, is the CPU-bound application startup time. What I mean by this - assume user already visited the page in past and has all assemblies already cached, the page will still take a noticeable while to become interactive because the application still takes a fair amount of time to start-up.
How will the Auto mode tackle this, if at all?

alienwareone commented 1 year ago

Will you also consider adding support for MVC controllers to directly render a razor component?

public sealed class HomeController : Controller
{
    public IActionResult Home()
    {
        return Component(new HomeComponent { Param1 = ... }, RenderMode.Static);
    }
}

We would benefit from