Razor Class Libraries (RCL)
Much of your Blazor code will be in Class libraries. These class libraries will be downloaded to the client. An application may use only one or two of the classes in a library that could contain hundreds of classes. When you publish a Blazor Web Assembly application and create the deployment package, the unused classes are trimmed from the assembly. So, the assembly in the production package may not be the same as the one being used in development. If a class is dynamically loaded and has no bindings to the classes in the application, it may get trimmed, and you may get a class not found error. If this occurs, you will need to configure the setting to not trim the class.
Use the Razor Class Library template to create a library named BlazorWorkbench.Pages. A RCL is a class library with a reference to the Microsoft.AspNetCore,Components.Web assembly and an _Imports.razor file with using statements to the referenced assembly. You need to add additional using statements for Blazor. You need to copy the using statements on the right into the _Imports.razor file in the RCL.
The template also created 4 example files that can be deleted, background.png, examplejsInterop.js, exampleInterop.cs, Component1.razor.
Create a folder named main in the RCL. Copy the files found in the layout and pages folder of BlazorWorkbench.AutoG.Client into the main folder. (see image)
@using Microsoft.AspNetCore.Components.Web @using System.Net.Http @using System.Net.Http.Json @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @using static Microsoft.AspNetCore.Components.Web.RenderMode @using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.JSInterop @using Microsoft.Extensions.Logging @using BlazorWorkbench.Pages @using BlazorWorkbench.Pages.Main
Modify AutoG.Client
Delete the layout and pages from BlazorWorkbench.AutoG.Client.
This causes an error to appear that it can’t find the lambda expression in routes.razor. To fix this:
Add a reference to the RCL and add the following statements into _Imports.razor
@using BlazorWorkbench.Pages
@using BlazorWorkbench.Pages.Main
Two changes need to be made in Routes.razor.
In the RouteView statement change the layout.mainlayout to just mainlayout.
Add BlazorWorkbench.Pages to the additional assemblies statement.
You should then be able to rebuild BlazorWorkbench.AutoG.Client.
<Router AppAssembly="@typeof(Program).Assembly" AdditionalAssemblies="new[] { typeof(Client._Imports).Assembly, typeof(Blazor.Workbench.Pages._Imports).Assembly}"> <Found Context="routeData"> <RouteView RouteData="routeData" DefaultLayout="typeof(MainLayout)" /> <FocusOnNavigate RouteData="routeData" Selector="h1" /> </Found> </Router>
In the main program file in BlazorWorkbench.AutoG the route map builder will scan for components with @page directives from a list of AdditionalAssemblies.
Add a statement to load the BlazorWorkbench.Pages assembly. Then add the assembly to the list of assemblies.
This step is not required for Blazor Standalone as it loads all assemblies and scan for pages on startup.
We added the BlazorWorkbench.Pages as an additional assembly in two places. The additional assemblies in the Program file, is added to the builder for the route map. If a page is not found when you navigate to it then it is missing from this map.
In addition to the page map Blazor also builds a resource file map which includes url paths to resource files in assemblies. Including isolated css. Failure to add the resources to the map will also cause you to get not found errors. The error does not tell you what is not found. If you see this then you may have failed to add an assembly to the list of assemblies in routes.razor.
app.MapStaticAssets(); Assembly pagesAssembly = Assembly.Load("BlazorWorkbench.Pages"); app.MapRazorComponents<App>() .AddInteractiveServerRenderMode() .AddInteractiveWebAssemblyRenderMode() .AddAdditionalAssemblies(typeof(BlazorWorkbench.AutoG.Client._Imports).Assembly,pagesAssembly); app.Run();
Run the App with the RCL
You should now be able to run Blazor.Workbench.AutoG using the RCL.
Repeat the process of removing the pages and configuring the other apps in the solution. When you run the second app, you will see that the title of the app is Blazor.Workbench.AutoG. The title is hard coded into the NavMenu.razor file in the RCL. We need to have the correct title for each app.
NavMenu is a BlazorComponent. It contains HTML that makes up the NavMenu for the MainLayout. In the MainLayout you will find the <NavMenu> tag which is where the HTML from NavMenu will be inserted. So, a Blazor component kind of looks like an html tag but it is actually a kind of macro that represents a page object, in this case a NavMenu. NavMenu.razor does not have any code in it.
When Blazor sees an @ it know that what follows is not HTML but a line of C# code. If you used cshtml in MVC this will be very familiar. In the first div replace the name with @AppDomain.CurrentDomain.FriendlyName.Replace(“.Client”,””)
<div class="top-row ps-3 navbar navbar-dark"> <div class="container-fluid"> <a class="navbar-brand" href=""> @AppDomain.CurrentDomain.FriendlyName.Replace(".Client","") </a> </div> </div>
Display Render mode
Modify the Home.razor page in the RCL as show in the image. Use RenderInfo property to display the current render mode name and to display the Loading dialog when not in active mode. The WasmG version of the app will take the longest to download to the client. Run the WasmG version of the app. When the home page is first displayed it shows render mode as Static and displays the loading message. Then in a few seconds, it changes to Web Assembly and the loading message is gone.
In order to display the Home page, in Web Assembly mode, the Web Assembly framework and the Home page code must be downloaded to the client. Since that has not been completed, Blazor “pre-renders” a static version of the page. The user sees the page but none of the buttons or clicks work until it has been rendered again in Web Assembly mode. So active pages include code to display a message that it is loading when pre-rendering. When it, re-renders in an active mode, the loading message goes away. Run the app in the server mode and auto mode to compare performance.
Pre-rendering is not just a Blazor thing. It is normal behaviour for Single Page Apps (SPA). An SPA downloads code to the client that generates the pages in the client. But this causes a problem for public web sites because search engine crawlers, scan web sites to update their search databases. They find links in menus to other pages and scan them adding the content to their search data base. If you find a site with Google, it is because Google crawled the site. If you decide to turn pre-rendering off or to only show the loading message on a public site, then your site will not be added to any search engine databases.
Pre-rendering does not have any significant effect on performance. It only occurs when a request is sent to the http server port. Navigation between components does not trigger pre-rendering.
Lazy Loading
When an assembly is loaded, dependent assemblies also get loaded. This will cause all assemblies to be loaded when the main assembly is loaded. For Web Assembly and Auto client apps, you may not want to have all assemblies loaded at startup.
The default configuration for Blazor apps requires all assemblies with pages to be loaded at startup so the page maps can be created. If the app has all of its pages in the client project, then they will be mapped. If the pages are in a separate assembly, you must add it as an additional assemble list in Program.cs and routes.razor.
Dependent assemblies can be configured to lazy load so they will not be loaded until needed. When a class in an assembly fails to find a class and a class not found exception occurs because the dependent assembly has not yet been loaded, Blazor will load the assembly that contains the missing class.
Identifying an assembly for lazy loading is only effective if the assembly is only used by certain pages. If you have an assembly that contains a base class, that you use in every page, no point in identifying it for lazy loading. This applies to any dependent assemblies used by the home page. Whatever assembly remains is what you can identify for lazy loading and see any improvement in startup time.
In order to lazy load assemblies with pages or to dynamically create pages at run time, you have to create a custom router. That is something to learn about in the future when you have a large app that might benefit from it. For additional information on routing see the post below.
Building a Custom Router for Blazor | Chris Sainty - Building with Blazor