>> Let's get started. Welcome to this talk. Thank you very much for
choosing to join us today. I'm very excited to show you
some of the great new stuff that we've been working on in
Blazor WebAssembly for.Net 6, My name is Steve, and I work at Microsoft on the Blazor
and ASP.Net Core teams. Of course, I'm very pleased that we've got some great new
stuff for you in this release. To set your expectations
for this talk, we will mostly be focused on the new WebAssembly specific
features for Blazor in.Net 6. There are other talks that will tell you about other
Blazor features, but we'll mostly think
about WebAssembly. Hopefully I'll inspire
you with some ideas from new app capabilities that you could create now that you
wouldn't have done before. As we go, we'll certainly
think about some of the impressive
performance improvements that are being brought
in this new release. To do all this, we're
going to need a scenario to build an application around
it and set some examples. Now I don't just want a
basic hello well thing. I want to think about
an ambitious business with lots of different parts
and different technologies. I thought, since I'm a billionaire and like most billionaires I
should have a space agency. That I would just set one up. I've created a space agency
that I call Blaze orbital, and I would like you
to come and work at My Space Agency as one of
the top software architects. To do that, you will of course, need to know a bit
about the business and the technologies that we
use. I'll tell you about it. We've got this group of
central servers and databases, and they deal with storing all the important business
data and the authentication, everything like that, and that's all implemented
with ASP.Net Core. But you won't need to
walk with that too much, you'll mostly be
focused on a front end. This part of the business is
called the manufacturing group, and they're responsible
for designing and building rockets and managing
warehouses and things like that. They've got a front end
implemented in Blazor WebAssembly. It's an existing application. Now there's another part of the
business called the Missions Team. They deal with people who
are actually in space and tracking the movement of
satellites and things like that. They've got a front end implemented with react. It's just
a different team. They've made a different
technology choice. Then there's a third part of
the business called Accounting. You probably want to get paid. You will want them to have
a functioning systems, and they've got an existing
application that's built with WPF. It's a native Windows desktop app. It's a bit legacy, but every
business has these things. You'll need to work with
that a bit as well. Now, I almost forgot, there's one other group and
these are the people who create shared libraries the other
teams in the company can use, and they insist on using only rust, whether or not that's
convenient to you. Let's imagine that you
take this job and you're working on the Blazor
WebAssembly manufacturing hub. Let's say you're using.Net 5, and you've been doing it for
a while and it's going well, you like it, you're
having a good time. But one day I come
to you, and I say, hey, I've got some new
requirements for you. We're having a bit of trouble
with our warehouses and tracking all our stock and need you to build a new inventory management system. Please take some notes, here are the feature requirements. I needs some very fast and powerful querying so people can rapidly cross-reference
where everything is. But you're not allowed to put any
new heavy load on the server. Because they're busy
enough as they are. Thirdly, this is a space agency. We've got to be fault tolerant. Networks can go down during
missions and we need your new feature to keep working regardless including the querying. It's not quite enough to only add this into the
Blazor application, it also needs to go
into the react and the WPF applications too
for business reasons. I know they're on
different technologies, but just figure it out and make it work somehow or that.
Will you please? Then finally, there's a need to print out stock
labels with QR codes, and the rest team has already
created a library for that, so please use that library that they've created in your application. I don't know how you're
going to use Ross, but just do it one way or another. That's a complex set
of requirements, but maybe there are
some new features in Blazor WebAssembly on.Net
6 that will help us out. Let's try it, shall we? Now I'm going to switch
over to my code editor, and I'll show you the existing
manufacturing hub application. Now of course it's secured. We need to login in
order to speak to the Secure gRPC M
point, so I'll do that. When I'm logged in, I'll be
able to access this data on the central servers about what's
going on in the warehouses. But we don't really care
about that right now. What we care about is
this Inventory screen. Now, if we're going to do powerful queries without
having to bother the server, and if we're going to have
to be able to run offline, we're going to need an
in-browser database. Wouldn't it be nice if we could use the industry standard embedded
database SQL light as well as. Net leading tool for working with
databases Entity Framework Core. Now that was not possible
in.Net 5 in earlier, and I will show you why. I'll show you what
goes wrong if you try. They've code already,
which is going to create a database context
NAF code DBContext and say that I want
it to use SQL light, and then there's a bit more code
that tries to create a DbContext. It will insert a new row into it, and then it will try
to query it back. But does it work? Let's find out. If I click this Try It button. What happens is, we get an unhandled error. Why is that? What's the era? We'll look in the
console and we will see that the underlying problem here is that we were not able to load
this DLL called e_SQLite3. Which makes sense.
Because is WebAssembly, you can't just load
random DLLs into it, and so for.Net 5 in earlier, that was just the end of the
road. You couldn't do this. But with.Net 6, we've added pretty
important new feature called Native dependencies, and that gives you the
ability to compile other code to WebAssembly and
link it in to your application. How about we try to use e_SQLite? I need to compile it to WebAssembly. I've got a command prompt here. If we look in there, you
will see that I've got the SQLite3 source code, and I'm going to compile
that to WebAssembly as a shared library using the
M Script and C compiler. The warnings are bogus,
you can ignore those. When I've done that compilation, I can now link it to my application. I'm going to go to my
project file and down here, just ear to where I've
referenced the SQLite package, this is the entity
framework package. I will add the new thing. The new thing is a
native file reference to the e_SQLite3 thing
that we just compiled. When you've done that, the next time you compile, you'll find it takes
slightly longer to build just the next time that is, because it realizes that things
have changed and it has to rebuild the WebAssembly binary and reeling kept with the
thing that you've just added. When that finishes, hopefully it
will reload inside the browser. Here it comes reloading. When it comes back up, I will try
doing the same thing as before. Do we get an error this time? We do not. There's no errors. It's actually working. It's successfully
running SQLite inside our WebAssembly application
and using EF Core in that, which is a whole new thing that
you wouldn't have done with.Net 5. That creates some powerful new
opportunities for you to do some new things with data inside the browser that you
wouldn't have done before. Let's imagine that you do
another couple of days of work and you create some
code that will fetch data from the backend and
it will synchronize it with this client-side
SQLite database, and we'll start building a grid
to show that data as well. Let me just jump forwards in time to the next version of
our inventory component, where we're going to do
some of that stuff already. We will need to rebuild that and we will get some hot
reload going in a minute, but I just pasted in way too
much code to be hot reloaded. When that comes back up, you'll see it's now doing something
quite a bit more interesting. It's fetching this data from the backend server and
it's showing it in a grid. We can even start working with
it before it's synchronized. But how is this actually working? Well, I made this little component called Data Synchronizer that
fetches stuff from the server, and then I've also got this sync status component that's
displaying the progress bar. Now the other code down
here is pretty basic, it's just getting an
EF Core DBContext, and then we're starting on
making a little grid for it. You can find all the code
for all of this on GitHub. I'll give you the link
at the end of the talk. Let's have a go at working
with this grid a little bit. I'm going to move this over here a little bit and resize
my window slightly. Now first thing I want to notice is that I can do things
like change sort order, I can scroll anywhere
I want very rapidly, even though there's a
100,000 items in this list, I can just instantly
jump to any part of it because it's a virtualized UI. It's very fast and
nice to work with. Also, I can change the code. Let's see if we can do some hot
reloaded code changes here. Let's say that these price incense, I want to format it as currency. Like that, I'm going to press "Save" and then we'll see
instantly in the browser, we retain the sort order
in scroll position, and now it's using
currency formatting. But it's actually wrong because
it says British pounds, but I'm going to pretend
that these are dollars, so let's change this like that. Now we got a dollar sign, but that's incense, so I
need to divide it by 100. That's a bit better. I want to have a comma separator, so I'm going to say to string
numeric with zero decimal places. That's looking pretty good. But I don't really want to repeat these dollar signs and
every single line, so let's get rid of that from here. I'm going to put it into the title
of that. That's pretty good. Because it's a number, I want it to be right aligned. That's pretty nice and
it's a pretty super experienced to be doing
that with hot reload, we can probably do some
more stuff as well. Let's say I want to change
the order of the columns. I'm going to put name
first, that's very quick. Maybe instead of displaying ID, that's useful as I'll display
the in-stock level like this. Stock like that. Cool. That's pretty good. What else could we do? Well, we could now just much
functionality to this as we like. Let's imagine that
you do another day or two of work on your application and you add a little bit of code that
deals with filtering as well. Again, I'm going to jump forwards to a newer version of this
where we pretend that we've done a little bit of work to support some additional
filtering stuff. That's going to reload
in the browser, and now you'll see there's quite
a bit more stuff going on. There's more columns. I've now got things
like this ability to multi-select categories and subcategories that's using
another new Blazor feature for multi-selected data binding. Then let's say, we'll come back to that in a minute. I can also do things like searching. Let's search for this
poltergeist stuff. You can see the updates
in real-time as I type. Again, I can still change, so all does obviously. Here's a more interesting one. Watch what happens when
I move these sliders. Look at the number in
the bottom left where it says showing a 100,000 items. As I move this minimum stock level, can you see how that's
updating in real time? I don't know, have smoothly
that comes across to you, but it's absolutely
perfectly smooth for me. It's a pretty amazing
user experience to be able to do this real-time querying. You basically don't
normally see this on the web because
it's hard to do this, especially if you're querying
the server every time. But when you've got local database, you've got the EF Core and you've
got virtualized UI from Blazor, this thing just all
comes together and it's a pretty magnificent
experience for the end-user. This is all very cool. Let's think about where we are on our journey to satisfying the CEO. We've implemented some fast
powerful querying and it doesn't involve any heavy
server load because even when we do this
real-time filtering, it's just using a local
single user database. Now what else do we
need to think about? What about this QR code thing? If I go back in here
and I pick something, lets have this, I don't know, Nose Connector whatever that is. You see this gray box here. Well, this is where we want to add a QR code so that the people in
the warehouse can print it out. That's already been
implemented in Rust. But how do we consume Rust code in a Blazor
WebAssembly application? Well, with.NET 5 and before you
just wouldn't do, but with six, again, we can use the native dependency feature
to reference a Rust library. I've created a Rust
library and compile it to WebAssembly using the
standard Rustal Jen. Again, you can see the code for this after the talk if you want to, but if I want to use it, all I have to do is add
another native reference, and in fact, I've already added it. Let's see the code for
our QR code component. Let's move this across
here and pick something. Again, that's difficult to see, so I'll just zoom out that. This is a slightly more low-level
native dependency because this time I've created a
DLL import method. This is the thing
that's been exported from the Rust library that takes the value for the QR code and
fills up a buffer with that data, and then I'm going to display
it in a Canvas element. If I change this to
call the Rust library, then as soon as I do that, the hot reload kicks
in and we now see a real QR code showing up here in the browser,
which actually works. Again, you can see the code
for that later if you want to. We've been able to
use the Rust library. Next thing, what about
making it work offline? Well, in a sense, we don't really have
to do any work to make that happen because Blazor, has always support offline
enabled PWAs with WebAssembly, and we've got a local database. It's just going to work. Let's try it to actually
verify this for ourselves. To prove that we can work offline, I am going to shut down the
web server that this uses. If I can find my command
prompt, here it is. I've shut down the
webserver completely. When I start up this PWA
that I published earlier, you'll see it looks and
behaves the same as normal, takes a little longer to
stop because it's trying to talk to the server and it
realizes that it can't, so we can't see any dashboard data. But if I go to the inventory screen, we still got all the data that
we had locally from ALEA. We can still do the
same filtering and so on that we did before in real-time, but we know we can't
talk to the server so we can provide UI around them. That was pretty easy,
we didn't really have to do anything
to make that work. That's pretty good. Time for a little bit more of
a challenge though. How are we going to put this into the reactant WPF applications given that they're implemented
with other technologies? Well, let's start with the mission
control application. Shall we? I've got a VSCode window over here, which is running this
React application. I'm just going to start
up in my browser firstly, so this is the mission control
application where we track the satellites and we count how long it's been since we've
seen any aliens and so on. Of course it needs to support
authentication as well, so I'm going to have to login with the same account
that I had before. That's using the single
sign-ins, so I'm logged in. What we really want
to focus on now is implementing this equipment finder. This is where we want to
use the inventory grid that we just created
in Blazor WebAssembly, but now we want to
use the same thing in a React application.
How can we do that? Let's find the source code
for that React components. Shall we? It's this one here. It's called equipment finder.js. If you don't know React this might look a little bit unfamiliar to you, but don't worry about it. All we're doing here
is keeping track of some text that's been entered
into a search box up here, and then we want to have some
more stuff at the bottom. Let's reorganize this
a little bit so we can see a bit more stuff like that. Cool. How would we add
the inventory grid? Well, one way we can
do it is we could just add an iFrame and display
the Blazor application in it. But that would be rubbish because it would be a separate application, it wouldn't share the same
authentication state, it wouldn't share the same styling, it wouldn't be easy to pass parameters in and get
them out and so on. It wouldn't be a lot better
if we could somehow just add the Blazor
component as if it was an HTML element like
a web component. Well, that is another new feature of Blazor
WebAssembly and.NET 6, and I'll show you how it works. In our Blazor application, if we want to export something as a component that can be
consumed from outside, we can do so in our program CS. In fact, I've already done it. Here I'm saying that
I want to register a custom element and I'm
calling it inventory grid, and that will be the
actual inventory component that we've been
working on all along. This actual extension method
here is a preview feature, but the underlying
infrastructure that makes it work is something that's
actually shipped in.NET6. Anyway, now I've done
this and I've added a script tag to my React application
to load the Blazor code. Let's see if it works. I'm going to reference inventory grid here inside
my React application, and when I press "Save", hopefully the hot reload system
for React will kick in and it will add our grid that comes
directly from Blazor. It's got all the same
functionality as before. It's working great. But not quite yet, because if I start typing
in the search box, you'll see it doesn't do anything. That's because I haven't
passed the search, into the search value
as a parameter. I am going to say the search
name that we're passing in is equal to the
search text from React. Then I'll press
"Save" and you'll see immediately Hot
Reload happens again, and it's applied my query. Now, as I type in real-time, it will update in
the UI. That's good. Now, another cool
thing because this is an actual component
and not an iFrame, I can change the
styling using React. Let's say everything else in this React application
uses a dark mode. I would like a dark mode
for the grid as well. I'm going to go into the
CSS for this thing here. I can say inventory grid table. We'll find the table
in the inventory grid, and we'll apply a filter to say, I want to invert it. Immediately we've got a
nice dark mode going on. Now finally, what about Hot Reload? If I've got some state in my React application and
I change something here. If I say super equipment
finder, you'll see, of course, it changes that state while preserving everything
else that's good. It's even preserved the
state of my.NET application. If I change my.NET code as well, for example, I'm going
to go here to the, let's change this
category title here to be cat name just for the
sake of making a change. I'll press "Save." Then back in the browser, you'll see immediately the.NET
Hot Reload kicks in as well. We can do.NET Hot Reload and preserve the state of both
the.NET and React code. We can do React Hot Reload to preserve the state of both
the React and the.NET code. Both Hot Reload systems are
working together and you can be super productive and I can give
you a promotion as a result, so well done to you. Now, last one we need to think
about is this WPF application. Now, that's adding
Blazor components to a native desktop application is not something that
shipped in.NET 6, but it's something
that we are adding with the marry release next year. I'm going to show you how that
might look right now very quickly. We won't focus on it too much. I've got the accounting
project here, which is a WPF application,
as I mentioned before. When I compile that and start it up, hopefully, that will
come up around now. There it is. Good. We don't care
about all this existing stuff. We just care about
this inventory tab. I just want to prove to
you that we can embed our Blazor component in that and make it integrate with
things like Auth as well. Of course, I have to log in, otherwise, we couldn't
talk to the backend. But when we've done our
exact same code as before, we'll just start working and have all the same capabilities as before. It really is the code that we just implemented with the cat name thing, and it all works the same as before. But I don't have time to really talk too much about how that works. What I'm going to do is move on from that and we'll
talk about something else. We've satisfied all those
requirements, which is brilliant. But we haven't talked much
about performance yet. One of the other big features for
Blazor WebAssembly and.NET 6, is ahead of time compilation. That means that instead
of running your code on a.NET interpreter
inside the browser, it can be precompiled to native WebAssembly bytecode
and run much faster. To quantify that, let's
consider a different example. Let's imagine that our
scientists have been creating a simulation of satellites
in a binary star system. Sounds cool, is actually basic, but I'm just going to run that now. It's a very simplistic
physics model here, but it is implemented
in.NET and you can see the code of it if you want it's
only about 80 lines of code. That's simulating these satellites moving around in a
binary star system. The question I'm interested in is, how many can we simulate before we start dropping below
60 frames per second? We've got a 100, can we manage 500? Yes, we can. What about 1,000? No problem, 2,000? Sure. Four thousand? Yeah. Still 60 frames per second. Five thousand maybe?
It dropped a bit. Maybe there I'm not sure. Six thousand and still
going-ish maybe 7,000? It's now well below
60 frames per second. This is not AOT compiled code. This is running on the interpreter, which is, fairly fast. But how fast could we
get it if we ran in AOT? I've published this application with ahead of time
compilation already. I'm going to start it up and we'll compare the speed to
what we had before. We know we should be able to
manage a 100, 1,000, 5,000. Of course, we should because we
did that on the interpreter. What about 10,000? Yeah. That's still working fine now. Twenty thousand? Yeah. Still 60 frames a second. How about 40,000? Again. Yes. Still working. Fifty thousand? Yeah. Still 60 frames a second. Seventy thousand maybe? No. It's dropped off now, but we've had more than a
10 times speed increase compared with the speed
of the interpreter. To really nail this down, I'm going to give you
some numbers on graphs. When I tested this earlier today, I measured 4500 satellites so that
we can manage in debug build. When I did a release compilation, it more than doubled,
which is great. That's still on the interpreter, we were getting 12,000
satellites then. But with the AOT build, we got a whopping
58,000 satellites then. You will generally see
these massive speedups when your code is CPU bound. AOT compilation can have some phenomenal speed benefits
for your application, but it does come at a cost. I want to communicate
the cost to you as well. Because I'm all about giving
you a realistic picture and not just making it look
better than it actually is. The realistic situation for application sizes on Blazor,
WebAssembly and.NET 6. First, let's imagine that you're building a very small application, such as the Satellite Simulator,
it doesn't do very much. When you publish this, you will find that a release
build there is 1.1 megabytes. Now that is amazing improvement
compared with.NET 5 because the smallest Blazor WebAssembly app
on.NET 5 was 1.7 megabytes. What we've done is added the ability
to strip out a lot more code, and that's how that
gets to be so small. However, if you AOT compile it, it will go up to 2.8 megabytes.
It's more than doubled. In this case, it's probably really
worth it for that speed gain, but of course, it is
quite a bit bigger. Now, as for the default application
that you get when you do a File New Project on.NET
6, that's two megabytes. It's slightly down from.NET 5, but it's still not that much
smaller because we haven't stripped out loads
of stuff by default because we assume you're
trying to use it. If you do an AOT built of that, it will come in at four megabytes. It is doubled that, it's faster, but it's bigger. Then finally, I want
you to think about a really big application because people do build really
big applications as well. It's important to be
realistic about these things. If you've got some very
big heavy defendants, then your application itself
will be big and heavy. There's no way around it. An example of that is Manufacturing
Hub because that uses EF Core, which is not designed for
code stripping in any way. We might do some optimizations
like that in.NET 7. But for.NET 6, if you depend on the EF Core, your app's going to be pretty big. That one is 5.5 megabytes. If we AOT compile it, it comes in at an
enormous 15 megabytes. Now, in this case, I would not
AOT compile the application because all the heavy lifting is
happening inside SQLi, anyway. The.NET code doesn't
really even break a sweat. There's not really any
point AOT compiling it. But in the case of Satellite
Simulator, I definitely would. It's up to you to decide for your application whether the
trade-off is a good one. That's all I'm going to have
time to talk to you about today. We've talked about AOT compilation, we've talked about adding native dependencies with SQLi in
our example in the Rust code. We've also looked at the dynamic
root components feature. That's the thing that
allowed us to add the component to a
React application. It would also work just
the same with Angular, Vue or any just plain HTML file because it's a web component
and you could use it anywhere. We've talked a bit about how
production apps can become much smaller if you enable all of
the code stripping features. We've looked at quite a few examples of Hot Reload through this talk. One thing I didn't
mention actually is the custom bundling
feature that allows you to control the shape
of the published output. You can read docs if you
want to see more about that. Thank you very much for
listening to this talk. If you want to see
the source code and try it for yourself
for all these demos, you can find it on GitHub at the URL that I've put
up on the screen there. That's all I have time for. Thank you very much and I hope you enjoy the rest of the conference.
Hereβs the link to the demoβs code shown at the end of the video: https://github.com/stevesandersonms/blazeorbital
Everytime I see Steve Sanderson's, I think back to the 2017 NDC talk that I attended in Sydney.
I left the room in awe of what I saw and with hesitant hopefulness that this would pick up steam.
So glad it did and it's gotten to where it is. Hope he's super stoked too
Would you use blazor for a production mobile app? Or is it too soon?
Steve's presentations are always nice to watch, the demo code themselves are pretty cool. The native lib linking feature looks pretty neat and could see it as useful even for non Blazor apps. EF Core and Sqllite for local db sounds nice to work with for local cached data and having all that zipped up nicely on a Blazor webcomponent sounds nice (albeit the payload is a bit bigger).
Also I've been using the webcomponents extension for a while now on some prototypes and it's really nice to work with. I can see it as a nice way to embed Blazor components to add interactivity to old projects (e.g. .Net Framework MVC, Angular1.6, JQuery etc...) while slowly migrating the whole app to .Net 6+.