ASP.NET Community Standup - Full Stack Blazor Tips and Updates

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
>> [MUSIC] Hello, everyone. Welcome to the September edition of the Blazer Community Stand Up. With us today, we have Daniel Roth. >> Hello, everyone. Welcome. >> Jon Galloway. >> Very excited to be here. Let's see some Blazer. >> Today the topic is full stack Blazer tips and updates. Part of this is going to be where Dan is going to go over some of the new changes coming in ARC1 for Blazer, and then I'll be giving a presentation after that about just a Blazer static server rendering overview and how it works and how it impacts how you build apps. That's that and I guess we should start by doing the community links. Here we go. First we have a blog post by Jon Hilton, Blazer SSR gets auto render mode in the latest.NET 8 preview. It's not just about auto mode, this is a general Preview 7 overview. It goes in depth about a lot of different features coming to Preview 7 like how forms work and root level cascading values and things like that. It's a pretty cool blog post and it goes fairly in depth. If you want to learn how to use some of those new features, certainly check that out. Yeah, so the next one is a pretty interesting one we have it calls itself a Blazer framework. It's a component library, but also it provides some abstract base classes for Blazer components, so normally components inherit from component base, but they provide alternate components with different mechanics around how they react to changes to state and things like that. It's a pretty interesting framework, but it also does include some pretty nicely styled components. They actually have a site here that we can look at, but they have various really beautiful looking components that you can use in Blazer apps. If you like this look, I think this would be a cool thing to check out. But yeah, they also have some helpers for rendering like render fragments I believe there was something on here about that. Then a >> [inaudible] reactivity. >> Yeah, it takes an alternate approach to handling changes to state. With component base, you have to state has changed method which allows you to indicate that the component should be rendered. But that gets called implicitly by things like event callbacks, but as far as I understand from this library, that's not true. It doesn't get called automatically. You have to call update manually, but then they also have special reactive value which does automatically trigger a state change. It's just like an interesting new approach for hindering reactivity in Blazer apps and I might have gotten something wrong there, I haven't actually personally tried it, but it looks interesting. I think. >> Reactive value, I don't know, it sounds like knockout to me for some reason, is it? But maybe not. Sounds like it's a value that is about when it's changed and can plumb into the component infrastructure to know that any things need to rerender. That's interesting. >> Great, it's great to see people innovating in this space. >> Yeah, it's super interesting. So I'm curious to see where this goes. Next, we have Blazer Barcode Scanner. This is a library that lets you scan barcodes and I think QR codes too. I was trying out my phone earlier with a barcode, but I think the light on my camera messes it up a little, so I'm not going to try to demo that, but it's pretty cool. If you need to scan QR codes or barcodes from a Blazer app, this is a pretty convenient way to make that work. Next, we have a new version of Blazorise, which is a Blazer component library. It's one of the bigger ones, and it has various improvements, various new components like Signature Pads, has a splitter component for resizable panels as well as enhancements to their data grid component, which I believe is based off the quick grid component that is shipped with Blazer. If you're using Blazorise, then try the new version. >> That's interesting. That off Canvas component there. >> Off Canvas? >> Yeah. >> Oh, yeah. >> Is that for custom drawing? Is that what that's on? >> Responsive design for desktop and mobile. I don't know. >> Yeah, I'm curious about that too. Cool, it sounds neat. >> In some sense, for me, this is one of the reasons why we need the community. There are things that even concepts that I was like, might not have even know about. We're certainly not all knowing and so when the community can go and explore these ****** and ideas and concepts, that just makes things better for everyone. It's cool to learn about these things and see people playing around with a stack. >> It's nice too because for some of these, they have to have opinions. They say, here's how we do components, or here's how we do charts or whatever and if Blazer did that at the bottom level, you lock people in, but when people build a library, they can say, here's how we do this certain thing and you get these different flavors of development. >> Yeah, absolutely. >> Last on the list, we have a YouTube video by Coder Foundry, Why 2024 is the Year of Blazor. This is a pretty cool video. It's a very positive perspective about the future of.NET and about the new things coming in.NET 8. It also shows an example that uses some of the new features. It's pretty cool, I will say. So definitely check out this video if you want another perspective on things. I think that's it for the community links. I think we're handing it off to Dan now. >> One other link if you want to share it. It's the blog post should be live by now. >> I'll check that out. >> Who is that guy? I also got my same jacket on. >> Very fresh blog post. >>.NET 8. At least candidate 1 is live. It just shipped right now, hot off the press. Download it, install it, get it on your machines. It's got a lot of great stuff in it. Just went live right now. >> All the Blazor stuff. >> Look at all the Blazor stuff. Easy way to get it, just go to.NET/next. That's a nice short link for the next preview release of.NET if you want to get whatever the latest preview release is. That has been updated for a release candidate 1, and so you can download it, install it. This is a release candidate, so that means that we are pretty much done. This is supposed to be a candidate release for the upcoming stable release of.NET 8, which is planned for November, every year new.NET version. Most of the features are in. Like most of the changes have been done with this release. Not all although, there are still some areas that we do expect some pending changes, Blazor being one of those. If you're looking for everything to be done in Blazor for.NET 8, we're not quite there yet with release candidate 1, we will have another release candidate next month, that will be release candidate 2, and we expect to be feature-complete, and done with all the big changes for Blazor at that point. A few more things coming from Blazor, but for the broad.NET platform, pretty much everything else is there and done and ready to try out. If you've been waiting, holding off on.NET 8, saying I don't know if I'm going to try preview four or five or whatever, I'm going to wait till it's more taking shape, this is a good moment to start kicking the tires. You can take your existing.NET 7 out, and try upgrading them to.NET 8 to RC1. Or if you've been following along with the releases, you can easily upgrade from.NET 8 preview 7 to.NET to RC1 as well. >> I don't know if there's a link to that next page if you want to show that Mckennon because I'm really interested. Like we've been working on this page and trying to make it useful to people, so it has the links to the newest stuff. Down at the bottom, we've got some top recommended videos which we're always updating. We'll likely put this one on there too, so this has all the preview blog posts and all that stuff. >> Good resource if you want to stay on the cutting edge of what's happening with.NET. Now, if you haven't been following along with every single preview release and you want to know what's actually new in.NET 8. Like how do I get a broad overview? Particularly for like ASPNET Core and Blazor, we have done some work to update the official release notes page that lives with the ASPNET Core documentation. Mckinnon, if you go back to the block post, there should be at the top. I think I mentioned this at the top, where to find this. What's new in ASPNET Core and.NET 8. If you click on that, hopefully, that link works. There it is. That's a summary of all the new features in ASPNET Core and Blazor that you can read through and check out the preview documentation for those features so you can get a full view of all the stuff that's new across the.NET 8 release from.NET 7. That's if you haven't been completely following along. Lots of cool stuff in here, obviously, the full stack web UI work that we've done in Blazor, but there's been work that's been done in minimal APIs, the native AOT work to support taking APIs built with ASPNET Core, and being able to fully ahead of time compile them. Lots of work in the authentication and authorization space. Tons of good stuff to try out. Way more than we can even cover in this one-hour Blazor community sender. Now, from.NET 8 preview 7 to.NET 8 release candidate 1. There's also a bunch of new things that wasn't there before. Let's take a look at that today. Let's go back to the blog post, and there's things across the board, but we'll be focusing on the new Blazor features. First thing in RC1, we have done a bunch of work to further improve and clean up the new Blazor web app template. This is the new Blazor template that's intended to unify our web UI story for.NET and ASPNET Core, so you have a one-stop shop for building all of your web applications. All of your web UI needs should be satisfied here. It's set up with all the new Blazor capabilities in.NET 8. Like support for static server rendering, where you can just render a Blazor or a component to the response stream in response to a request due to an endpoint. Very similar to the rendering that we've always supported with MVC and razor pages, and even back further with.NET. We go back to web forms and some of the older frameworks. You can now do that pattern with Blazor components, the template is set up with that. There's the progressive enhancements of static server rendering. Like the ability to do enhanced navigations and form handling. That's where Blazor will actually intercept the page navigation to prevent the need for a full page reload, for a full page refresh, when you're going to a new page. It will instead intercept that request and do a fetch request down in Javascript. Then the rendering still happens from the server, but Blazor then takes care of looking at what's actually changed based on what was rendered from the server and patching that into the DOM. There's no web sockets involved here, there's no WebAssembly. It's still doing server-side rendering, static server rendering, but it's doing it in a more enhanced and seamless way. This makes your app feel more like a SPA app when you're navigating around. It's fast, it's smooth. You don't see that blip when the page reloads, but it's still leveraging the server for the actual rendering. Streaming rendering is enabled in the template. This is when you have pages that do long-running async tasks, but you still want to get pixels down to the browser as fast as possible. Streaming rendering, will do an initial render of your Blazor components with some initial HTML and some placeholders for content that's going to come later while you go and query the database, or do an API call. That update can then be rendered from the server with a separate component render and streamed to the same response stream so that the UI can be updated. That's streaming rendering, and then, of course, all the normal interactive modes that Blazor has supported for a while. The Blazor Server render mode, Blazor WebAssembly render mode, where you want to have a component that can deal with button clicks and drag and drop, and full rich interactivity. Also, the new auto render mode, which uses server and WebAssembly together. We start out with server so that the app loads fast while we download the Blazor WebAssembly run time in the background. Then once it's downloaded and loaded, we can then switch to using that run time locally. >> Go ahead. >> I have a quick question on that auto render mode because I honestly didn't understand. It's stringing the WebAssembly down. Does it switch over automatically or is it on next navigation or something, that it's going to load? >> I'm going to let Mackinnon answer that. This is Mackinnon's feature actually, he's been doing a lot of work on this. When does it actually switch Mackinnon? >> If a component was already initialized with a Blazor Server render mode, it will stay that way until the component gets disposed. But after the WebAssembly bits are downloaded, then new components that are added to the page will start using Blazor WebAssembly. You don't have this complicated state transferring system that will switch a Blazor Server component to a Blazor WebAssembly component. Once the WebAssembly bits are downloaded, from then on, your components will use Blazor WebAssembly. >> Got it, okay. >> Often this happens on another page load. You had the components, they were using Blazor Server, the user comes back to that page and now it shifts to Blazor WebAssembly. But it doesn't actually have to be a full page reload, right Mackinnon? If the component initially rendered as Blazor Server and then you did something in the UI that caused that component to just no longer be on the page. Then the Blazor Server circuit can be cleaned up at that point, and then you do something else on the page that causes that component to come back. When it comes back it will actually be Blazor WebAssembly instead of Blazor Server or even within that , that's possible too. The next time you use that component, is the way to think about when auto will do the switch. It will check to see is the WebAssembly run time there? If it's there, then it will use it. Otherwise it falls back to the Blazor Server. Let's look at the template a little bit. I'm going to show some of the new things in the template. It's got some new options, it's got some new layout of the files. Let's see what we've done. Can we switch over to my screen? Perfect. I have already downloaded and installed.NET eight RC one. I've installed also the latest Visual Studio update that just went out today, 17.8 Preview two, so make sure you get that. You'll need that to have a good dot and eight tooling experience. If you're a Visual Studio code user, you can also use the C# Dev Kit extension in Visual Studio code. Let's go ahead and try and create a new project and I want to create a Blazor web app, let's go ahead and create a Blazor web app. Project, that looks like a good name. Here I want to point out that we've got some new options that are showing up in the template that we didn't have before. First of all, we now have the "Use Interactive WebAssembly components" option. This option will turn on the ability to actually render a component using the WebAssembly render mode, and we want to really push it all the way down to the client. You could do this before with our previous.NET 8.0 Preview releases but you had to set it up manually. Now the template will help you do that. We have the existing use interactive server components. This is the one that will set up Blazor Server for you with your interactive components. What's new is it's now enabled by default, if you forget to check it, no interactivity is working. Hopefully that will become less of an issue. We'll just always turn on Blazor Server based interactivity because you've already got a Server, you might as well leverage it. Then lastly, we have a new option for including the sample content of the template. The counter page, the weather page, these are great and awesome components but not every app needs a counter in a weather component. This is basically the equiva***t of what we used to do with empty template, we used to have a separate empty template. We've decided just to make that an option where you say, "Do you want the sample content or not?" If you don't want it, just uncheck this check box. It'll remove the sample pages and also it will remove Bootstrap so you can use whatever CSS framework that you love. Whether it's Tailwind or pick whatever it is that suits your fancy. Okay? >> Look like you've basically answered Andy's question here. You're saying it's there, the option for the empty template and that's basically it, right? >> That's the option, yes. We do have the option for the empty template. Just uncheck this checkbox when you're done looking at the sample content, and you will now have a more blank Canvas, shall we say, for your Blazor web app. I'm going to create this project as it is with the Server option selected. First, I'm going to leave WebAssembly unselected so we can see what just doing Server looks like. You can see we get a single very clean project and a few things are different in here. One thing that's different is that we now have a new folder layout for the content of the Blazor application. I'm just going to get here. We used to have this pages folder. It used to be top level, and then we had a shared folder. We've cleaned that up and decided, let's just go ahead and create a top level components folder and all of your Blazor components will just live under there so they're easy to find, easy to manage. There's nothing semantically meaningful about this components folder from the frameworks perspective, you could name this folder whatever you want, you don't have to use this folder if you don't want to. It's just a pattern and a convention that we've decided to now start using in the templates. We still have the pages folder where all your routable components live. It'll be under here. We'll expand that in a second. We got rid of the old shared folder because really the only thing that was in there was the layout. Let me expand these so we can actually see what's going on inside. There you go. The shared is now just layout and that's where we've got your main layout and the Nab menu components. Those are unchanged but they're just living in a different folder. I always thought shared was a bit weird like sharing what? What are we sharing in that folder? Some people would put their just random components in there, is like, oh maybe this is a place I can just take components. Now you've got the top level components folder for that, so hopefully that's a little cleaner and more convenient. Here's our pages, same pages as before but we've renamed the files to match their function. The names before were a little obscure, a little unclear I would argue. The counter component is the counter. We've renamed the what was index thought razor to just be home because it's the homepage for your app, which I think is nice because that's how we talk about it. We don't usually say this is my index page, this is the home page. >> That's a holdover from MVC days, right? >> Yeah, it's an old school name, I don't know. Maybe people will like this, maybe they won't, let us know what you think about these names. We know we're expressing some opinions here, moving people's cheese a little bit. If you think it could be done better differently, let us know. Then what used to be the fetch data component is now just the weather component because that's what it does, it displays a weather page. It still shows patterns for getting data and rendering them, but now I think it has a bit more of a clearer name. Other things that are different. In App.razor, we've done a bunch of work to clean up this file and make it simpler, easier to parse what's going on here. Things that we've changed. First of all, we have removed the Bootstrap icons. Those are no longer there. Let me put my notes for show. I forget anything that we've removed from here. Before we used to use this really old icon set called local iconic, which I think has been defunct for a while. Sorry about that, that we kept shipping that for a while. We initially thought, "Well, let's switch to the Bootstrap icons." Those turned out we're big. Luckily a little heavy for the app size. Now we just have a few custom icons that we include in the template when you check the sample pages content. If you don't do that, then you don't get that content and you can use whatever icon set you'd like. >> Those are just like SVG static files and? >> It's just SVGs in the CSS. Pretty simple. >> Oh, in the CSS. >> The default Blazor error UI is no longer in the app component, we've moved it over here into the main layout. This is the little bit of markup that will show up if there's an unhandled exception that gets detected when the Blazor up is running. We moved into the layout because you tend to need to think about how the AUI should interact with the rest of the layout of your application, so that you can customize it and make it reasonable for your application. If you're wondering where that is, it moved over into the layout. Then we have simplified how routing is set up by introducing this template routes component. This is not a built in Blazor component, this is just a component that lives in the template. If we go to its definition, we can see all it's doing is setting up the Blazor router. This is a little simpler as well. You'll notice that we only have a render fragment for found. There's no render fragment for not found. That's because thanks to static server rendering where we have proper as core endpoints for each of the Blazor routable components in our app. The not found content of the Blazor router actually just never gets used. You don't actually need it, so we've dropped it from the template as well. Last thing in App.razor, I'm going to come back to routes in just a second because there's some interesting nuances to that component. But the last thing we changed is the Blazor script tag. You'll notice that it no longer has the suppressed error attribute on it. It used to be that with Blazor components, we went out of a way to try and keep you from putting script tags into what were historically always interactively rendered components where dumb elements can come and dumb elements can go. Script tags and components didn't really make sense in the past because there was no way to really remove them. If you had rendering logic that said, "If something is no longer true, then don't render the script tag." Well, that wouldn't actually do anything from an HML Dom perspective. But now that we support static server rendering, script tags in the component is actually a very legitimate scenario, we're using it in the root app component for the application. That error is no longer there and so we've removed that suppress error attribute from the script tag. You should still be aware of the issues of using script tags. If your component is interactive, like if it's a Blazor Server component or a Blazor WebAssembly component, you probably don't want to have script tags in those components but we're not going to prevent you, if you decide that's what you want to do, the framework is not going to get in the way. Now I want to go back to this routes component, because this routes component is interesting. Why did we introduce this separate component? Yes, it makes the App.razor a little shorter and smaller, but why not just in line, the Blazor router right here in App.razor? Well, there is actually a really good reason. The first question you might wonder is, well, let me back up. The main reason is that we wanted to make sure that it's easy for you to enable interactivity at the root of the app instead of just on a single page. Right now, with the Blazor web app template, we really only enable interactivity for one page. We turn on interactivity for the counter. The counter has a button, you click the counter and the count goes up. That's where really the only on click handler that's happening and that exists in the Blazor web app template today. >> But what if you want to have interactivity throughout the app, like what if you want to use the Blazer client side router? If you want to have interactivity in your layout, then you need interactivity to be at a higher level scope or maybe even at the root of the application, which we think it will be fairly common. This is basically the way Blazer server and Blazer WebAssembly worked in previous releases. We want to make that easy, and so that's why we factor things into this routes component. If you want to, for example, use Blazer server, you can just say at render mode, then render server right here on the route's component. Now the whole Blazer Router and all the components that it renders will use Blazer server. You're probably going to also want to put this on your head out. I think Mckinnon is going to talk about this in just a little bit, but to really make everything in the app fully interactive, you want the components that live in the root component to be interactive. Now you might wonder, well why don't we just make app.razor interactive? Why not put the render mode attribute right up here at the top? We just say what is it like at attributed render mode server right here? Well, the reason is is because you can't, the app.razor component, the root component from your app needs to be static. It needs to render statically. It can't be an interactive component, in part because of that issue with the script tags. The root component is the thing that really needs to render the Blazer script, and you can't remove script tags, so the root component really can't be interactive. That's not a thing that will be allowed. If you try to do that, you'll get an error. We can't put it at the root component. Well, why can't we just put it like on the router? Why not just take the Blazer router, and stick it right here, right in line, and then put the render mode attribute right on the router component? The reason why that also isn't going to work is because, well, when you make a transition in Blazer from static server rendering to an interactive component, the component parameters for the interactive component need to be serializable, like that component might be running on WebAssembly in the browser. You need to be able to flow the component parameter values to that component while it's running potentially all the way on the client in the browser. The router component in Blazer has render fragments for its parameters, and those are not going to be serializable. Rendering an interactive component with non serializable parameters is also going to generate an error, so hence the need for the routes component. It provides a nice boundary between the static server rendering of our application and the interactive rendering. That's why that's there. Hopefully, that will help people who might have those questions. That's how we've simplified app.razor. It's nice and clean. Any questions about that? I know I went through a lot there. >> There's a bunch of questions. Do you want to rip through some real quick? >> We can. Yeah. Let's go through a couple. >> All right. Let's see.- >> Did I break the app there? All the changes- >> One question you showed using Visual Studio to create the app. Is there CLI switches for all that stuff? >> Absolutely, yes. You can do everything CLI, first with.NET. Let me see. We get a new Windows terminal up here. If I want to create a little bigger, there we go. Let's go to my desktop and I will do.NET New Blazer is the short name for the new Blazer Web App template. We had Blazer server. Blazer WASM I think was the Blazer WebAssembly one ,.NET New Blazer will create a Blazer Web App. I figured that then you'll get the Blazer web app template and it has options for server, use WASM. The same option. I think [FOREIGN] empty it looks like I have a new Get feed that I don't have authentication support for. I need to clean up my new get feeds. It has the empty option on it as well, so all the options that we surface in Visual Studio, those will be available from the CLI as well. >> Okay. >> You're a Mac user and you don't have a full visual studio template creating experience or Linux user, you'll be able to create a Blazer Web App. >> Okay, let me sea few questions on the switching betweens. How does debugging experience work when switching between server and WASM? >> Good question. We already support this today. The Blazer WebAssembly code that's running in the browser on a WebAssembly run time. We support debugging that code, and the way that's done is through some very tricky, fancy stuff, we actually go through the Javascript debugging protocol, like we have to connect to the browser through the Javascript debugging protocol, and in the middle, we stick a.NET debugging proxy that will augment the Javascript debugging protocol with dot net specific concepts that allow us to understand what's happening. From a.NET perspective, we have that and at the same time you can also connect the normal.NET debugger to your server process. Visual studio can connect to both of those things at the same time. You should be able to hit breakpoints and inspect code, whether it's running on WebAssembly or running on the server. We should probably create one of those projects. So far I've only created a server project. >> All right. >> This is interactive. Like you can see that I can click the button, the count goes up. That's using Blazer server for the counter page. Just the counter page. The homepage is static server rendering like this is just sending requests, getting content and rendering it. There's nothing interactive about this page, and then on the weather page, we've got the weather table. You might have seen there's that little delay. Before the table gets rendered, you click "Loading". Why is that happening? That's streaming rendering, that loading dot dot is simulating like doing an API call to some proper weather surface to actually get the weather data. It takes a minute, but we get pixels on the screen immediately, and then a half a second later you actually see the weather content. That delay is totally simulated by the way. Like if you look at the weather component down here is where that's being done and it is literally just a task dot delay. [LAUGHTER]. The weather page is slow and you're wondering why. It's because we put a task dot delay in your template code just to demonstrate streaming rendering. >> That's not making an API call, that's just directly on page. >> It's not making an actual API call. The key aspect here is that it is async, like you're doing something async that is long running. Blazer will render the component immediately, when initialized gets called, it does some of the async work, so it immediately returns the task and Blazer will immediately render the component with whatever state it's got. Initially we have no weather forecasts and that's why we get the loading dot dot user interface and then later when the task completes because our task dot delay is done and we got all the weather forecasts as if we had made an API call or done a database query or whatever Async work it is. Then Blazer detects that the task is now completed and we'll render the component again, and that's when it streams and update to the same response stream, like it's just one request. You made a request, you got initial batch of HTML, and then half a second later, you get a little bit more HTML in the response. Blazer then takes care of patching that into the DOM using that Blazer.web.script that we saw in the. >> It's not like a web socket or anything, it's just one long HTTP response stream. >> One request. I mean, long, it's like half a second. In this case, if you had really long running Async tasks, it could take a while just like, but it would have taken that same amount of time anyway, whether you were streaming or not. You would just have the user sitting there looking at their blank screen wondering, hey, is this working? What's happening? Why am I not seeing any content yet? What nice thing about streaming rendering is you can put Pixels in front of the user immediately while those longer running tasks are happening, the normal request timeouts that exist in SM core will then apply. If it takes too long, then the server might decide this request is having a problem, I'm going to end it or maybe the client is misbehaving in some way, so I should kill this request to save on those server resources. >> Yeah. Okay. >> Yeah. >> Those are all there. That's all the server side rendering based features, both static server rendering and interactive server rendering with Blazor server. Let's do Blazor WebAssembly because that's a little different. Let's create a new project. Blazor Web App 2, and now I'm going to check the checkbox to say yes. Give me some WebAssembly with that and we will have both. Now, we can do both server and WebAssembly interactive components. Let's go and create this, so now we don't just have one project anymore. Now we have two projects and this is a little different than what we had originally envisioned and set out to do it with dot net eight. Originally when we were prototyping things, we thought oh man, it would be cool if we could put the stuff that's going to go down to WebAssembly and the stuff that's going to be on the server. Let's just put that all on one project and we can use like multi targeting to decide what builds for what and then you get a single project experience for both WebAssembly and server. We ended up deciding for dot eight not to do that. Why is that? Well, the reason is that the code that you build for WebAssembly, you really need to think carefully about well, how much code should go down to the browser, what dependencies do I want to go down to the browser like maybe you have dependencies that have proprietary code in them or sensitive code that you don't want to ship publicly to the Internet with Blazor WebAssembly, that code those assemblies will be available to anyone who then downloads them. When we tried to do that with a single project model where we were using multi targeting, it was very difficult to reason about and control what got built for WebAssembly and what got built for the server. It was just too easy to accidentally like pull in a large dependency or some service specific code into the WebAssembly part of the built, so we kept those separate just like we did with Blazor WebAssembly and previous releases. We have a separate client project that represents, this is the stuff that's going to go down to the browser and then the server project is the stuff that's just going to stay on the server. It does make a couple of things a little harder, but we think that clarity is really critical for people who are trying to build this style of web application. If we look at what we got here so that there is also a small workaround that's currently in the template that is actually was not needed and we'll clean it up, I'll show you how to clean it up, but in the client project, let's start there. We have a counter component. This is the counter component that's actually going to handle the button click and increment the count and you can see that it has been attributed with an interactive render mode, and because we have both server and WebAssembly turned on we just went ahead and said you know what, you've got both. Let's use auto, let's use the goodness, the fancy new thing, so this counter component will initially start with Blazor server and then once the run time has been downloaded it will switch to blazer WebAssembly the next time you initialize the component. Now the workaround I was mentioning is that you may also see wait a minute, there's another counter component up here in server. Why is that there? This counter component all it's doing is calling the client counter component and it has the route and you can see it's got this little comet in here that this is a temporary workaround until we can actually discover routable components for static server rendering that are in another assembly than the main assembly which is funny because we have that support in RC1, but we just didn't update the template, so this was just a little something that didn't quite get done for RC1. This will get cleaned up for RC2, so we'd actually don't need this server counter component, so what I'm going to do to clean that up, I'm going to get rid, I'm going to copy the route and I'm going to move it over into the client one and I'll show you how to do this the new way. I'm just going to delete now the server Counter component, so we don't need it. It's going to come from our client project and now in program CS here we can see that this is where setting up support for server rendered components and WebAssembly rendered components is being done and then down below we actually enabled the render modes. Down here is where I'm going to make on that additional call to add additional assemblies and this is where I can manually specify that I would like routing to discover routable components from assemblies other than just the assembly that this app component is coming from, so I'm going to do typeof (Counter). Assembly, so we'll have the assembly there, so that should allow the server project to find my counter in the coming project. >> If I've got a bunch of components, I'm not going to need to say that for counter and weather and blah, blah, blah, there's a way to say like go get them all? >> You'll have to do it for each additional assembly that you have routable components in, but you only need to do it at the assembly level. You don't need to do it at like a per component level. I'm just using the counter component here because it's a convenient way to get the assembly where that component lives. >> Cool. >> That should now be it and let's go ahead and run this. Let's see if it's working properly. Cool, so now we've got our new web app. Now before I go to counter, let's go ahead and bring up the deb tools. Let's see if we can see auto in effect with this template, so let's look at all requests and that looks good, so I'm going to go to the counter component now and we got a whole bunch of stuff that's being downloaded, so first of all do we have any WebSocket connections? There is the Blazor Server WebSocket connection being set up, so this should work. I can click counter is working. Do I also have any WebAssembly? I got a whole bunch of WebAssembly now. What is up with that? Well, first of all let's just search for dotnet, so here's the actual dotnet WebAssembly run time. It's now called dotnet.native.wasm. I got renamed in dotnet and actually don't know why, but it used to be just dotnet.wasm. The runtime folks needed to give it a new name, so what they did. That's the actual run time, so what is all this other WebAssembly that's being downloaded like all these guys. Well, in dotnet we've introduced this new web friendly packaging format for your assemblies called WebCIL I'm going to call it which is we took the dotnet assemblies and we strip off all of the native window executable stuff from them, like DLLs are based off of the Windows portable executable file format and when you're running dotnet assemblies in the browser using WebAssembly, you're not running them natively on Windows, you're running them on the web platform using a dotnet run time built for WebAssembly, so you don't need any of that native Windows executable stuff and actually it's problematic because a bunch of like highly more restrictive environments will see like wow, that's a Windows DLL. It's being transferred across the network. Why is that happening? Let's just block that. We'll then block the DLL transfer and then your Blazor WebAssembly app doesn't work because of security software getting in the way, so we've repackaged the assemblies now, so they no longer have all of those like somewhat scary looking bits. To be clear all the code in a Blazor WebAssembly app always runs within the security sandbox of the browser. It cannot run natively on the device because the web platform won't let you [inaudible] But this just like avoids looking like you're doing something more nefarious than you're actually trying to do, so that's what's happening there, so we've now downloaded also the dotnet WebAssembly run time and the app bundle in the background. It's still using the WebSocket and I think we can see that if we like bring up the WebSocket. Let me clear all these messages and if I click you can see the binary messages are flowing across that WebSocket as we use Blazor Server, but now if I refresh this page, let's go ahead and do that. >> This WebSocket people are like, why is there another WebSocket there? You can see over here, this is actually some visual studio tooling that's kicking in. This is how we do hot reload and CSS Hot reload and stuff. You still see a WebSocket that's not because Blazor is using Blazor server, that's just part of the tooling. >> Static 101, so 100 is continue. I don't even remember what 101 is. >> 101 is the upgraded protocol. When I want it to go from just HB to an actual WebSocket protocol, that's how you do the transition. We should now be running on WebAssembly instead of server. Can I still see? I don't even see the Blazor server connection anymore, but is that because I cleared it, Mackinnon actually? Maybe I've cleared it by accident. >> It's because you refreshed the page. >> Oh, yeah and we got a new. I didn't have preserve log. One thing to note is that in.NET 8 RC1, when you're done with Blazor server, the circuit will actually still stick around in RC1. We haven't done the logic yet to clean it up. Once all the Blazor server components are gone, we ideally should then just clean up all the circuits. In RC1, the circuit will actually still just stick around while the app is running. In RC2, we are doing the clean up work so that you only have the circuit live while there are Blazor server components that are active on the page. We've just switched from server to WebAssembly. That's the auto mode. From here on out now that we've cached the.NET runtime and the app bundle, it will use Blazor WebAssembly from here on forward. >> Cool, wow. >> Now, things to note, when using WebAssembly, the code that you want to run in the browser needs to be built from this client project. While it's really easy to take a component and say, hey, I want you now to be a Blazor server component. Remember what we did with routes where I just went to app.razor and just added render mode right here? That was really easy. It's very easy with server when you want to then switch to WebAssembly. If I want to say at rendermode WebAssembly. >> It says, renderserver it should say rendermode. >> Okay, thank you. Well, let's say I want to do that. Well, this component right now lives in the server project. >> Yeah. >> It doesn't live in the client project. So when you make a transition to WebAssembly or auto, you will have to move code around. You'll have to move the routes component into the client project. Now in.NET 8 RC2, we will provide another option on the template that helps you do that. If you want your app to be fully interactive at the root and you want it to be maybe server or maybe WebAssembly. Making it WebAssembly means moving that code into the client project. We'll provide a template option that just does that for you. But if you have your own components, like a little island of interactivity on a page, and you start you initially thought, oh, that should be a Blazor server component, but then you change your mind. That will mean doing a little project refactoring. You'll have to move it into the client project so that it gets part of that build. Something to be aware of. That's the new Blazor web app template. I think I've hit all the new goodies that are in this project. Yes. I think we've touched them all. There's other stuff that's new in RC1, I'll just say the top two briefly because I know we've got some other stuff that Mackinnon is going to show. There's improvements to routing. We've updated the Blazor router to now use the same implementation as the ASP.NET core router. That means a bunch of features now light up for the Blazor router, like default values. All of the built in route constraints are now supported in Blazor pages and complex segments, like if you have a pass segment that you want to have be partially a route value and partially just a fixed value. That's now supported in Blazor's routing system, whereas it wasn't before. There's been some nice improvements to QuickGrid. This was actually a community contribution from Elder James. Thank you, Elder James. Wherever you are. He added a feature where the QuickGrid component will now pass through any additional attributes to the underlying rendered table. He also added a feature to the form validation, where you can now easily check if a field is valid or not. Let's see what else. There's some new runtime features as well. There's a new trimming feature for people who are doing ahead of time compilation where you can now trim down the.NET DLLs, well, the Web CILs that get shipped with your application. Before we needed both the pre-compiled Wasm and also still needed the.NET assemblies for cases where we had to fall back to the IL interpreter. We will now do trimming on those assemblies to remove unused code. There's a new option that you can try out for that. There's also a new runtime API for configuring the.NET runtime with various low level runtime features. Like if you want to change the virtual file system path location, or even simulate environment variables from the browser. There are a bunch of low level.NET runtime APIs in Java scripts that you can use to do that. Those APIs are now available for Blazor apps. Lots of good stuff. Mackinnon is looking at me like, Dan, we have other stuff to talk about so I'm going to go ahead and stop here. >> I know. >> Go and read the blog post and give it a try. Mackinnon, I think, now is going to must be a little bit more detail on [inaudible]. >> I have a question, because we've got 20 stared questions queued up. I wonder if we could go rapid fire on some of these before turning over to Mackinnon. Because I know Mackinnon is eager to get going, but I do want to get some while they're still topical. >> Let's do it. >> How about I'll run through and any that you want to pass on for now we'll get to later or something. Cool. Let me see one. Is there a remote development container? I'm not really sure. >> A remote development container. I mean are they talking about like? >> Depth container maybe or codespace. >> Code space thing, maybe. I don't know. I would check the.NET 8 blog post. The top level one, not the ASP.NET core one but the one for the broad.NET 8 RC1 release and see what they list there. I can't remember off the top of my head. >> Okay. >> We do ship container images for.NET 8 with each release so there definitely are docker container images that are available for.NET 8 RC1, but for remote development container, I'm not sure of that one. >> Okay. This one I think you answered here, interactive Wasm component still on a separate project. You did show that. >> It does too. For.NET 9 we'll look again to see if we can get to that single project model. But for.NET 8, yes, you will need a separate project. >> Cool. Is there an option for Core hosted? >> That's that new option, I was talking about that in RC2, we will add an option that you can make the route of your Blazor web app interactive. That will then give you the equiva***t of the old Blazor server template and the Blazor WebAssembly template with the ASP.NET Core hosted option checked. That's what we'll be adding in the next release. Not in this release, this release, you have to set that up manually. If you want to do the semantically equiva***t thing for ASP.NET Core hosted Blazor WebAssembly app, that's a long phrase, you can do it, you'll just have to move the routes component, set its render mode to be WebAssembly or auto and all that stuff in order to get things in the right place. I do have a sample project that I've been migrating forward with each of the.NET 8 previews to show how to do that. In RC2 it will get easier. By the way, if you have an existing Blazor WebAssembly app or Blazor server app, you don't actually have to change anything to get it to work with.NET 8, you can just change the target framework version, update the packages, and it should just work. If it doesn't, let us know, because that should just work. If you then later decide, oh, I want to try some of these new features that are available only with the Blazor web app model. We will then provide you guidance on how you can shuffle things around a bit to use those new features, but it's not required.NET 8 is absolutely backward compatible with existing Blazor apps. >> That's a really key point, I always talk about that. You can just update. You don't have to use the features. You can just update your version and you run faster and you get better, things light up if you want to use them, but you don't have to. Cool. Let me see. Is data transferred or if so, how between server and Wasm? >> Do you want to speak to this Mackinnon? >> Well, there's another question here too on Flux or just state management in general. How do you folks think about that? >> I can take a step. When you transition that component from server to WebAssembly, there's nothing that will then capture state from the server and shuffle it down to the client for you. We do serialize the component parameter. The component parameters are the main interface for how data will flow. Whatever you pass as parameters to the components, that data will then be available to that component regardless of where it's rendered. That's why they need to be serializable. But if you had some state that you were maintaining while it was a Blazor server component and then the component goes away, well, that state is effectively gone now. Then you come back to that component and you're like, oh, no, I wanted that and I want it now over on the browser. Those are all exercises for the developer to figure out how do you want to do that. Blazor in general is fairly unopinionated about how you manage your component state. It's a class with fields and properties. There's the DI system, you can put state and services. There are cascading values and parameters where you can cascade state down through components. But we're not prescriptive about which pattern you use and how you use those tools. Some people like the state container patterns like Redux or Flux and there are.NET versions of those that you can use with Blazor apps. Some people like the MVVM pattern and you can implement an MVVM pattern with Blazor if that's what you want to do. But it's not like something that's prescribed by the framework. We just saw that. Was it Ingus or the framework from the community? It obviously has a reactive model for dealing with state. The sky is the limit. We're not prescriptive about it. You do have to decide what works best for your application, for your development team, for your team culture. >> Cool. A few more real quick ones here. If you've got an existing Blazor Wasm app, can you use SSR? >> Yes. >> Yes, so actually technically you can do this today. You can already do it because we have the component tag helper which can do static server rendering from a razor page or from an MVC view. You can set up a Blazor WebAssembly app today to do prerendering. We don't do this by default in the templates, but we have docs on how you can render your Blazor components from the server and then set them up for interactivity with WebAssembly on the client. That's how you would typically handle that with a Blazor WebAssembly app. You can have static server rendered Blazor components that sit beside your Blazor WebAssembly app as well. You notice I had that map Razor components call, which is what's rooting looking for all the routable components in the app and making them available as pages. You specify which root component you want to use and the assembly, where you want to find those components. That can live right alongside an existing Blazor WebAssembly app that's using the old Blazor WebAssembly.js file. That should work. Yes, you can. If you want the seamless transitions and the new progressive enhancements, then you'll want to take that Blazor WebAssembly app and start to massage it into the new Blazor web app patterns. >> Cool. I'll do two more quick ones here. Minimal API with Blazor, would that be a separate project, and you just make an HTTP client in your Blazor app to call back into it? >> The server project is an ASP.NET Core project. Blazor is part of ASP.NET Core. In your program CS file, you can configure whatever endpoints you want, including minimal API endpoints, NBC controllers, Razor Pages, they can all live together in the same ASP.NET Core project. It's one happy web framework. >> Like you said with routing being united and all that it's one system now. Cool. Last one. This is near and dear to my heart. If you've got an Azure Static Web static app, do you just continue to do Blazor [inaudible] with functions on the back end? >> Great question. I love this question. Static web apps is for a static site. It's basically a bunch of files that are going to be put on a CDN and globally distributed. Standalone Blazor WebAssembly apps where all you have is Blazor WebAssembly, you have no active server piece to your app. Those can be hosted on Azure Static Web apps. We actually are going to continue to ship a Blazor WebAssembly standalone app template, specifically for that scenario where you want to be able to publish a Blazor app to a static site hosting solution, like Azure Static Web Apps. The Blazor web app template is oriented around the idea of, hey, I can give my users a much better experience if I can leverage the server to do cool stuff like static server rendering, streaming rendering, these enhanced navigations and form handling. Interactive modes like the server interactive mode, where I'm leveraging the server to make things load faster, feel faster, feel smoother. With Azure Static Web apps, the static site hosting part of it obviously can't host an ASP.NET Core application by itself. You can't do that just with Azure Static Web Apps. Now Azure Static Web Apps does also have this feature where you can bring your own back end with it. Where you can pair it with Azure App Service or with Azure Container Apps, and you use both together as a single solution. We think that will be one way that you could do a Blazor web app. Definitely the simplest thing you can do is just take a Blazor web app and publish it to Azure App Service, and that will definitely work. Azure App Service can host ASP.NET Core processes in [inaudible] and all that stuff. You're basically then just taking the WebAssembly part and hosting it as static files from within that app service. Being able to then break, pull that just the client part out, and put that on Azure Static Web Apps with the rest of it living on Azure App Service is something that we're actively talking with our friends on the Azure team about how we can facilitate that, make that easier. With a server project, you're going to need something that actually can run a server. >> Last question, and hopefully this is something McKinnon is going to be covering or something. But is there authentication? >> I'll talk to this. In.NET 8 for ASP.NET Core we have the new ASP.NET Core identity API endpoints that allow you to programmatically interact with identity, so for logging in users, getting a token, or setting up a cookie. All the identity flows like password resets and all these types of things are now manageable using the Identity API endpoints. For Blazor, we are also trying to build a identity UI around that functionality using Blazor components. That work is happening right now. McKinnon is nodding his head because he's been directly involved with this effort too so that we can then include hopefully that code in the template. It is coming in hot. RC2 is the last preview release for.NET 8. But as far as last we talked about it earlier this week, it is on track and we're still planning to add it. Having an integrated Blazor experience for the new of story that's in the next candidate release. It is not available with the current one, you'd have to manually construct it yourself. >> I think with that, I should turn it over to McKinnon and let him get going. You're ready? >> Sounds great. I'm ready. Yes. Awesome. Today I'll be talking about Blazor Static Server Rendering. What's new, how it works, and what I, or you the developer, should do about it. The reason I'm doing this topic is because in.NET 8, the capabilities of Blazor are elevating dramatically. With that comes a lot of new content to learn a lot from your functionality, but also maybe some confusion and ambiguity as well. This presentation is about clearing up some of the nuances about how static server rendering works and how those actually impact the way that you build apps using Blazor. Before I jump into the main content, I want to clear up some terminology that I'm going to be using in this section. One is static content. When I say static content, I mean static from the perspective of the browser. It's content that doesn't change after it's initially loaded or rendered on the page. Typically, static content yields faster load times because you don't have a bunch of JavaScript or WebAssembly that has to load and present the content on the page. The content is just being displayed directly by what the server returns. >> Some examples of frameworks that took this approach are Razor Pages and MVC. We also have interactive content. This is content that's dynamically updated by client side logic that's running in the browser. This is capable of reacting to user input and changing content on the page without having to fetch new pages from the server again. Some examples of this are Blazor Server and WebAssembly components. Another thing I want to clarify is static server rendering. This is a term that I don't think we've used before today, I think publicly, what I mean by this is rendering static content from a Blazor endpoint. This is not to be confused with the Blazor Server, which allows you to render interactive content where your code is still running on the server, but it's using SignalR to update the page without doing HGP requests to update the page content. >> I think static rendering appears in our code. We have APIs that call it static rendering. For .NET 8, me in particular, I was using the phrase like server side rendering often to talk about what here we're referring to as static server rendering. The problem with calling it server side rendering was, well, what kind of server side rendering do you mean? Do you mean the Blazor Server kind, or do you mean the static kind? It was unclear. I think it is good as a new term that helps makes it clear that we're not talking about the Blazor Server version, we're talking about just rendering to the response. >> It looks there's a comment that has come up about that as well. It's weird to call it SSR, but then say static server rendering. Yes. Because server side rendering could mean two different things in Blazor because we already have Blazor Server which provides interactive rendering but it's still running on the server. That's where this clarification comes in. >> Kristopher, I'm with you initially. I originally thought, well, a lot of the other frontend JavaScript frameworks used the term server side rendering to refer to the pattern that we're now implementing with laser components in .NET 8. So let's just use that term. Let's just re-use the existing industry term. But they don't have this problem. Most of the frontend JavaScript frameworks don't support interactive server side rendering. When they say server side rendering, it's very clear. Well, it's the non-interactive kind. We have this unique feature which is the ability to make a component interactive from the server. We need some way to clarify that we're talking about either the interactive version or the non-interactive version. Static versus interactive is the current thinking on how we talk about that? >> Exactly. I think we've clarified that. Let's move on. Another thing I want to do, I'm talking about this, is try to call out the similarities between what exists today and what is coming new in .NET 8 because there are a lot of similarities and I think clarifying what those are can help people understand what's actually going on better. It turns out that static server rendering isn't really a new thing in ASP.NET Core. This already how Blazor apps worked in general. You have some static content on the page, maybe this includes maybe some meta tags in the head, and then maybe at the bottom of the page, you have some footer or maybe the Blazor UI, that static content. Once it's rendered on the page, it doesn't change. Then the interactive content is where your Blazor app actually lives, that's where your components are getting rendered. That's the stuff that changes as you're switching between pages in your app. You already have static content that gets served, and then interactive content that lights up after the initial page load. An example of this is Host.cshtml in Blazor Server. In this case we're using Razor Pages. This is a Razor Page right here. This is all static content. Once this is on the page, it's not going to change. But then we also have the component type helper, which allows you to add interactive content to the page. It's following a similar pattern where you render from the server and then later interactivity starts up. This pattern is true not just for Blazor Server, but for Blazor WebAssembly too. If you have a static site, you have some index HTML file, and then after that gets loaded on the page, your WebAssembly app starts up. You make some call to, I don't know, something.recomponent.add to add your re-component and then you get interactive rendering via Blazor WebAssembly. >> Builder or something? WebAssemblyHostBuilder, I think it's WebAssemblyHostBuilder. >> Yeah, WebAssemblyHostBuilder. That's it. Then, now we have this new thing, the Blazor web template, and this follows the same pattern. You have static rendering from your app.razor file and then you specify somewhere in the component hierarchy a render mode to indicate the transition to interactivity, and then interactivity is carried out, either using Blazor Server or WebAssembly. The cool thing about this last approach though, which is the new thing, is that it's all Blazor. You don't have to use two different pieces of technology to get service side rendering and client side interactive rendering. What are the advantages of doing things the new way? Well, one is that you get a unified way of doing things. It's a single technology stack. You're not mixing Razor Pages with Blazor and you don't have to worry about slightly different syntax and it's just a consistent developer experience overall. If you have Blazor libraries, you can use them for service side rendering if you want to. You don't have to worry, it's just less stuff to learn overall. Also, you get to utilize the benefits of both Blazor Server and Blazor WebAssembly. This is something that Dan actually demoed a little bit earlier with the auto render mode. Blazor Server has the advantage that it generally results in a faster page load time, like the time to interactivity at least is smaller. But the disadvantage is that it requires a constant connection to the server. If you lose that connection, then you lose interactivity in your app. Blazor WebAssembly on the other hand, it takes a little bit longer to load initially, but once it's loaded, you don't need a connection to the server so you're not putting extra load on the server that you might not want. The auto render mode is great because you can use Blazor Server at first while the WebAssembly bits are downloading in the background and then switch to WebAssembly to alleviate the server from controlling how the app is rendered. Or if you want to use both on the same page, maybe some components only work with Blazor Server and similarly work with Blazor WebAssembly, you can do that as well. There's a question. >> Let me try and guess the answer here, but we had historically two different models. Now we have one unified model. I think the scenario now we'd recommend basically for everybody is use the new unified. If you're new to all this, just use the new model. >> There might also be some aspect of this which is also, like even within the unified model, there are a bunch of ways of doing things. I could do static server rendering, I could do Blazor Server rendering, I can do Blazor WebAssembly rendering, I could pre-render things. It is a lot to reason about and I'm very sympathetic to that additional complexity. In our role as framework designers and developers, we are trying our best to make it easy for people trying to build the best app possible, to use the appropriate architecture that's going to make sense for your application. With modern web apps, there are nuances and complexities that are now part of the app development experience in order to make that app as good as possible. Like should I be using streaming rendering in this page or should I be handling everything from the client? What should I do? There's not really, unfortunately, one pattern that just fits it all. You often see these arguments on various websites where people will debate about should you do everything on the client, should you do everything on the server? They'll have all the frontend JavaScript developers arguing with all the backend server developers who are used to doing server side rendering on which one way is better. Reality is that both of those techniques have appropriate places in an app and it's part of the app designers job to figure out, well, where should I use each of these features so that my app experience is as good as possible? Can I avoid having that loading spinner on my banking website while you're downloading a giant JavaScript bundle? Would that have been better if I had just done server side rendering or static server rendering for setting up that initial content? These types of user experience concerns, unfortunately, involve a lot of these decisions. We're trying to make the features available and we know we have work to do to provide docs and guidance on when should you use what? How should you think about when each render mode is most appropriate? >> Cool. >> Absolutely. I hope that later in this talk, I'll be giving some demos. Hopefully that will clarify some examples of, when would you want to enable interactivity on a page or for a component? What are some of the things that you could run into? But just covering this last point. Another reason to do things the new way is because we have really nice server side rendering features coming to Blazor, including something called enhanced navigation and enhanced form posts and streaming rendering, which makes your service side rendered app feel more a spot even though it isn't. I will get into that deeper later to hopefully clarify exactly how that works. There are two topics that I wanted to talk about today and I picked these based on issues that we get in the ASP.NET Core repo. We get some issues that indicate that there is a lack of clarity with how some of these things work, with how render modes work, and then how enhanced navigation impacts the functionality of the app. These are two topics that I'll be going a little bit more in depth with today. Let's start with render mode. What is a render mode? It just describes how a component gets rendered. An example could be a component is rendered statically from the server. It could be a component is rendered interactively using Adobe Blazor like Server render mode or using Blazor WebAssembly. The render mode is just how a component gets rendered on the page. When you use these new API's map Razor components, the root component starts with an implicit static server render mode at the root. So if you don't specify any render modes in your app, it's going to be a static app all the way through. Then on a component subtree basis, you can enable interactivity. If you have a page or a certain component that needs to be interactive you can enable interactivity on a case by case basis. I'll show an example later of how you might realize that a component needs interactivity and then go and enable it. But just keep in mind that static rendering is the default. Going from rendering statically on the server and rendering inactively is what we consider crossing the render mode boundary. The reason it's a boundary is because your code is running in two different places at two different times even though it's in the same app. When you render statically, your Blazor code is only a live for as long as the response last. Once the response is complete, your Blazor code is no longer running. After that interactivity can start. >> That's the more long running Blazor state in your app, I guess. But I'll talk more about that later as well. Then another thing is at least for a.NET8, the interactive render mode of sub-tree can't be changed. You can't say of transition from the server to the client using Blazer Server. Now you want to render another sub-component or another child component using Blazor WebAssembly, that isn't something we support at the moment, but we do support having Blazer Server and Blazor WebAssembly components on the same page at the same time, as long as they are the first render mode after transitioning from Blazer Server. >> Siblings can be different. >> Yes, but once you're interactive, your children have to use the same interactive modes your child components. You'll get an error if you try to nest like a WebAssembly component instead of a Blazer Server component, for example. Let's do a quick demo of how this works. What we have here is this is a project created from the template. It had server interactivity enabled, but I've commented out all cases where we actually use server interactivity. What I'm going to go ahead is first run this app and show how the app behaves as a fully static app. I'll opened on my other screen here, but you can see it's the template we're all familiar with. You've got the Home page, the Counter page, and the Weather Forecast page. If I go to the Counter page and click the "Click Me" button, you can see it's not incrementing, which might be surprising, because if we go to the Counter page, you can see that we have an onclick handler. Why isn't the onclick handler running in this case? The answer is because our Blazor code isn't even running at this point in time. It only runs to serve the page initially, and then after that, there's no code to handle this click. What we need to do in this case is make the app interactive in order to code that runs on the client, to be, to be able to react to those click events. What I'm going to start with is go to the app component and I'm just going to make the routes component interactive here. We can say rendermode = RenderMode.Server. This is using Laser server render mode and I know it might be confusing because you might think, wait a minute, I thought server side rendering was the default. Well, static server rendering is the default. RenderModeServer means interactive server rendering and you can see that from the XML docs that come up here. >> One of the changes we're considering actually before we finished.NET8 is should we rename server to be something like interactive server and change the render modes to make it clear that which ones are interactive or not by putting interactive in the name, that might help. It's looking like we might actually try to make that change, but we're still discussing it. >> I'll go ahead and run this app again. What we can see here is if we go to the Counter page, we can click and the counter now increments because we have code running on the client. It's still running on the server, but it's interactive. Our code is still active even after the response completes. It does that using a WebSocket connection as you can see from the console here. But what's interesting is that even on pages where we don't need interactivity, the connection is still in use and it's still alive. If we actually go to the "Network" tab and I look at the WebSocket connections. You can see that even though we're on the Weather Forecast page, we still have the Blazer Server connection. If we click around, you can see messages coming through as I click through the app, even though the Weather Forecast page and the Home page don't need to be interactive, this is unnecessarily wasting server resources by keeping this connection open. What we should do in this case is just to make the Counter page interactive. We can go ahead and remove this here and the Counter page will add attribute[RenderModeServer}. What this is going to do is now the connection will only be active when we're on the Counter page. If I pull this up again and pull up the console, I can go to the Counter page and you can see as soon as I navigate now the connection starts and now the counter is interactive and if we click back to the Home page and wait a couple seconds, the connection disconnects. This isn't actually something that's available yet in RC 1, but in RC 2, this will be the behavior that you observe when the circuit is no longer in use. When that website connection is not being used anymore, it gets disconnected and your app is fully static server rendering. >> Is this the actual RC 2 implementation? >> Yes. >> We're seeing RC 2 bits right now. That's the first time I've actually seen that work in the RC 2 bits. That's cool. Well done,. >> Yes. It's looking into the future, I guess. >> One question again that I think people ask is when you rendered the counter component statically initially and it just didn't work, I think some people might wonder like, why didn't you tell me, why did you let me fail, why don't we provide an error or a warning in that case? >> Well, so there might be times when you have a component that you want to work with static rendering or interactive rendering. It's totally valid for example, if I were to pull the counter functionality into a separate component, maybe I want to be able to still render the "Counter" button, but not have it be interactive in some cases and then let whoever renders the component decide if they want it to be interactive like we did with the routes component here. It's not necessarily an error to not have onclick handlers be available. >> Actually by default we render all interactive components statically at least once. Because in.NET8, all of the interactive render modes, Server, WebAssembly, Auto, they all have pre-rendering enabled by default. Like the initial request to that app dot Blazor component will statically render everything into the response which then sets up the script tag and that's what then will trigger interactivity to be enabled. But everything had to be statically rendered as part of that pre-rendering step and you don't want that to be an error. That's why you don't see a warning error because we don't know like, you might also be rendering it and that might have been absolutely the intended behavior. >> Totally. Actually that's something that we've seen people get confused about. Here I've just override the uninitialized method, and then I'm just going to output the console initialized like the component was created. What we can do now is run this again, and one thing that surprises people is if we go to the Counter page and I'm also going to pull up the console here so you can see what I'm talking about. If I go to the counter page you see that initialized was lodged twice, which can be confusing because we only see one counter here. Well, the first initialization was when we were initially sending the pre-rendered content down to the client and the second time was when the interactive content or the interactive component got initialized. There were two components created at two different points in time, one during pre-rendering and one after interactivity started. Likewise, if I were to implement disposable in this component, let me go ahead and close this, then we would actually see that it gets disposed once before it even gets created as well. It'll get disposed twice as well like once when you initialize the page and then once you navigate away from the page. >> Two instances of that component, like you get an instance created while you're doing pre-rendering and then you get an instance created for the actual interactive mode. Like if it's on WebAssembly though those two instances live in completely different processes. In Blazer Server, they technically live in the same process. Right now, it is still two separate instances even if it's pre-rendered and then Blazer Server, I think we still have an item in our backlog to look at, like, could we do state full pre-rendering where we actually somehow maintain which component is used. It has some complexities associated with doing that. Right now, it does still create two instances. >> Absolutely. Another thing that we've seen people get confused about understandably, is let's say I wanted to make the current count in this component reflected in the page title. I'll just say, counter and then current counter here. Intuitively, you would think that this should work because of course, like I wouldn't it. But if we go and run the app, you go to the Counter page and click, we can see that the counter is still listing zero as the current count, even though in the main content of the app we can see that it's incrementing. Why is that happening? The reason is because the way page title works is it uses a new feature in.NET8 called sections and this allows you to from one component rendered to a completely different part of the app. In this case we have page title which is going to be rendering to the head outlet component. If we go to App.razor, we can see our head outlet is placed right in the head over here. But we don't see is an interactive render mode specified. What's happening is the head outlet is getting pre-rendered. It's showing the initial page count, but then after the counter starts up as being an interactive component, it's going to look for an interactive head outlet to render to and there isn't one. That's why the page title doesn't update. If you want to have an updated page title, we need to have both the component that's up into the page title and the head outlet itself be interactive. I'll go ahead and specify rendermode = RenderMode.Server and that will allow the counter to increment. If we go here, click "Enter", then we can see that it's updating. However, one thing to keep in mind is that by making the head outlet interactive, we've just made our entire app interactive because the head outlet is present on every page. If we go over to the Home page again, you can actually see that the connection is no longer disconnecting because the circuit is still in use. Something you want to be careful about when you're working components for interactivity is that they're not interactive unnecessarily, like you only want the parts of your app that have to be interactive to be interactive and that will result in the most efficient app. >> This is going to be interesting I think because the idea of scoping interactivity in the app so that you can reduce resource utilization, you reduce the burden on your server, those types of things, I think is very appealing but it does also seem like it's very easy to get to a state where you're really just going to need the whole app to be interactive. If you want any interactive features in your layout like the head outlet or anything else, then now the app's going to need to be interactive from the root. We'll have both options available. I actually don't know yet which is going to be most common. Are there going to be people that find that for most apps that can actually scope the interactivity in such a way that it's useful and meaningful? Or are we going to find that most people find, you know what, I'm going to need the whole thing to be interactive anyway, so I'm just going to do it at the root. I think that's an unanswered question for us. Community, let us know what you find as you build apps and start playing around with these bits. >> Yeah, great points. Jon is saying something very important. >> Super and that's all I have to say about that. I'm interested in this because we used Blazer in.NET website in the live shows and this is something where I personally want to try and play with the different models on this. How at the component level or, probably for that just a page level. >> Yeah, I think that's a great example of an app that already exists today that does have this island of interactivity notion. Most of the.NET website and dot.NET, it's all built on.NET. A lot of it is just razor pages doing server side rendering and there's some JavaScript. It's nothing it gets a little bit added on those pages. Then we have the live.NET page, which uses Blazer and has, full interactive Blazer features. We're actually in the middle of an exercise to migrate the whole.NET website to just use Blazer. It will be interesting to see where, we end up having requirements like, "Oh, I run a little widget in the nav menu bar thing of the.NET Website." And how we deal with those issues. Does the whole website end up just being interactive anyway and leveraging auto mode? >> Yeah. >> Sometimes, I hate to say it and it's going to offend some people out there, sometimes it makes sense just to put a little bit of JavaScript right there because that's just a lighter weight thing to do. >> That's a good point. Deciding to use Blazer doesn't mean you can't use some JavaScript. You do have to be thoughtful about Don Management and all that stuff, but you can. >> Yeah. >> There was one question which I think is useful here. That example you showed on initialized was called twice, and it is something you need to think about. You shouldn't probably be calling an API necessarily on initialized, but it's something to think about, how your events are fired and that. >> Yeah. >> Yeah. >> You can't deal with that though. That is absolutely a pain point. You need the data. You're trying to render the components. If you're getting the data from an API endpoint, then you got to go get it. One thing that you might wonder is, "Okay, well. When I get it the first time, can I just reuse it? Why go get it again? Can I just save it someplace and then reuse it?" The answer is yes. We have a feature for persisting, the pre-rendered state. The state that you used to do the initial pre-rendering, you save it into the page, basically gets embedded into the HTML so that when the interactivity is set up, you can then just read it out of the page again without making the API call, and you're like, "Oh, I already got the data, I don't need to make another API call, I'm good to go." That's a persisting pre-rendered state feature that you can basically have a little logic and non initialized that says, "Do I have a state already? No? Okay, go get it. Now, save it." Then when you check again, "Do I have it now?" It will find it. >> Yes, this is interesting from Damian here about static components that weren't tied to the overall app and render mode and share data between the app and static islands. A lot of interesting stuff. All right. >> We have a little bit more. >> All right. >> I'm going to move on to the last section of this. That's about enhanced navigation. Before I describe what enhanced navigation is, I just want to first talk about the kind of two types of navigation that can happen. Someone is like a traditional page navigation. If you have a server side rendered site and you click a link, it's going to completely reload the page, it's going to send request to the server, the server is going to respond with some HTML. All state in the page is going to be lost, or at least all the JavaScript or document state is going to be lost and replaced with what the server returns. Compare that to a SPA navigation that uses client side routing. When you switch pages within the app, the client side logic determines what your content gets displayed, and it doesn't require fetching a new page from the server. As a result, JavaScript and DOM state gets preserved across navigations. There's a lot less to load when things work that way. But with Blazer, what we want to do is have service side routing if you have a static server rendered app, but then also be able to preserve state across navigations. That's really useful for cases like, let's say you're building YouTube actually, because YouTube does this I think, if you have like a mini video player in the corner of your app and you want to switch between pages still within your application, but keep the video playing, you want that element to be preserved across navigations, and that's what enhanced navigation lets you do. It also lets you preserve interactive components. If you somehow have an interactive component that gets preserved across page navigations or that stays in the same place across page navigations, then it will actually retain its state rather than being obliterated and then recreated when the page loads again. This is what enhanced navigation is all about, it's all about sending a request to the server and then using that to display the new content, but then making it feel more like a SPA navigation. How it works generally behind the scenes is it just does an HDP fetch for the new page content and it does not navigate. It doesn't set window out location to something, it just gets the new content and then parses it as a document fragment. Then it runs this fancy algorithm to compute a difference between the content that's already on the page and the new content that's coming in from the server. Then applies the minimal set of changes so that it preserves as much of the existing DOM state as possible, between navigations. This has many interesting implications. One is to get faster, more efficient navigation. You don't have to reload all the assets when you move to another page. If they're already in memory, they can stay there. We also get to preserve document state, like what I was talking about with the mini video player example. You also get to preserve interactive component state. These are all great advantages. It also does come with some other interesting implications, and that is, dynamic changes to static content get reset. Let's say you had some JavaScript that would add some content to the page, let's say it would add a link tag for things like theming, like if you wanted to link a style sheet dynamically based on some like light mode, dark mode, theme setting. If you switch pages, enhanced navigation will actually remove that change because it'll say, "The new content coming from the server doesn't have that link tag because it was added dynamically." Therefore, that tag gets removed and then you lose your styling. In.NET eight, this isn't available in RC one, but at.NET eight, we're going to add a data permanent attribute that lets you preserve DOM content on a hierarchy basis. You can mark an element as data permanent. You can do that dynamically, even and then when you switch pages, that element will be ignored, in enhanced navigation. You can preserve elements through enhanced navigation. The other thing we'll be addressing is that some page loading mechanics are skipped. Let's say you had a reliance on window.load, like the load event, when you navigated between pages. Well, because enhanced navigation isn't doing an actual page reload, that load won't run when you switch pages, so maybe your initialization logic will get skipped. Or maybe you wanted some inline script to run when a page was loaded, but now that isn't running, because it existed on the previous page and it's not going to rerun when you switch to the new page. For that, we have enhanced navigation callbacks, or at least we're going to add them, where you can listen to enhanced navigation events and then run your page specific initialization logic there. But these are just some things to be aware of when doing enhanced navigation. We'll also have a way to disable enhanced navigation if you need to in certain cases, or you can disable it globally, which I'll demonstrate in a minute. But we generally recommend you don't do that because it's pretty cool. Yeah. >> Wow. >> Let's move on to the DEMO. >> What I'm going to do first is actually show what the app looks like without enhanced navigation so we can see why it's so great. What I'm going to do is just set this auto start property to fault. This is going to prevent Blazor from starting when the script tag is seen. Then I'm going to have another script tag that starts Blazor manually. This is so that we can pass an extra option to disable enhanced navigation. It's going to do Blazor.start and then I send SSR options, disableDomPreservation. >> For those of you who are like, wait a minute, Mackinnon, why are you showing me JavaScript? I thought this was a Blazor, a community standup. This is code before Blazor has even started up. There's not even a chance. We haven't started running.NET code yet. This is the bootstrapping logic. >> Exactly. If I run this, this is going to behave like Blazor pages app. When we switch pages, you see a little flicker there where we actually do a full page reload, and I'm not sure if it's coming up on the screen share, but every once in a while you'll actually see a visual flicker when I switch pages. You can see, if we go to the Network tab even, let me switch to all, then you can see when you switch pages it's reloading all the assets on the page. They're cashed in this case, so it's okay. But still it's doing more than it has to. What we want to do is make it so that the only request that's happening is for the page and nothing else, just for the page content. Let's comment this out and remove this. Now, I can show you what it looks like with enhanced navigation enabled. We have the same page, and if you go to the Network tab and click the Counter page, in this case, it's starting a WebSocket connection. You'll see a little bit more. But if you switch between, for example, the Home page and the Weather page, it's only requesting the exact content that it needs to display. It's not losing any other state on the page, there's no flickering, it's just a very smooth experience. Also, if we were going to have an interactive component that persisted across these navigations, it would keep a state. I can actually show that as well. I'm going to create a new component and I'm just going to click Counter button. I'm going to copy most of the code in the counter and just put it in there. Let's take this, paste it in here, and let's remove this, and let's display the count directly in the button. We do Count, not that. There you go. Then what happens is if we were to put this, we can put it in the layout. I'm just going to put it right next to the about link. We can do a counter button and give it a server render mode. Let's say rendermode=RenderMode.Server. Now what's really cool about this, actually I'll just wait until I show you. If I increment the count bunch and then I click to the next page, you can see it keeps its count even though we fetched a new page from the server. This was a server side navigation, but the interactive component is keeping a state on the page. Imagine this was like a video player, that would keep at state as well if we were switching between the Home page, the Counter page, and the Weather page. Whereas if we were to go back and turn off enhanced navigation, and you can see it does not work that way. Now, I can increment the count, I can click on Counter, and you can see it just got reset back to zero. That's what enhanced navigation is doing. Is it's preserving as much state as possible even though it's a server side navigation. I think that is about it for enhanced navigation that I had. Are there any questions? >> There are questions but we are super over time. I think we should maybe wrap up and then we can go deeper on some of these for next time. Maybe we can take to look at some of the questions that we got and pick some favorites for the next standup. >> There are a lot of questions. >> There are so many. It's overwhelming to even try and pick. > Maybe in addition to a URL links thing, we also need the after the fact question answer thing. >> You're right. Tons of great questions. I think we probably really can wrap them up. There's some common themes, there's some discussion. Some people are saying they don't love the naming of the RenderMode and they think it should be, I don't know [inaudible]. >> Was there any good counter proposals for RenderMode? >> Dynamic render. I don't know. Honestly, we'll have to look. >> That debate can be taken to GitHub feedback like that, file issues, comment on existing issues. We welcome that discussion. >> One that I just want to pop up here is, this is pretty cool. I just like seeing this. This is an interactive shopping basket which totally makes sense. It's in your component and it's preserved during enhanced navigation. This is really cool to hear. That's an example of exactly like a super useful thing there. >> Hi, Marina. Marina has been helping us out with the Blazor project on the repo. She's one of our very active community contributors and issue triager. You may see I'm a bit familiar with her name as well. >> You know what? Here's one. There's a lot of questions on authentication. Maybe that's something we could also dig in to a bit in the next stand up. > That would be awesome. We could definitely do that. For the RC2 bits should have the off bits there, and we should be able to show that. I think almost every block post that we've done for Donna Date, I've had someone ask, where's the authentication stuff? We know people are really interested in it, and I apologize it's coming in so late. There's just been a lot of stuff to deliver this release. >> What happened in this release? Well, I think let's play us out. I'm officially almost 15 minutes late for a meeting and so cool. Thanks everybody. This is amazing. Thanks for the amazing demos. Keep the comments coming in. I can dump them out to an Excel file and we'll try and triage them a bit. >> Bye, everyone. >> [MUSIC]
Info
Channel: dotnet
Views: 21,645
Rating: undefined out of 5
Keywords: blazor, dotnet, aspnetcore
Id: 47CZqb53nCM
Channel Id: undefined
Length: 104min 1sec (6241 seconds)
Published: Tue Sep 12 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.