Now we are going to take that reuse one stage further and put our component in a Razor Class library.
We ended the last article with with a Blazor Web Assembly app that had our component in it.
Our first step is to Create a Razor Class Library. So Right click the solution and Add new Project.
Choose Razor Class Library
and then create it, don't tick the pages and views box:
Clear all the files except the _Imports.razor:
So we now have an empty class library and we want to move our component to it. You can either drag and drop or right click to Cut and then paste, but Move the following files/folders from our webassembly app to the razor class library.
- The sourceJS folder - make sure it copies across the hidden node_modules folder, the src folder, package.json and the snowpack.config.js
@using Microsoft.AspNetCore.Components.Web @using Microsoft.JSInterop
Now we need to remove the snowpack generated files from our web assembly app. So delete the contents of the web assembly apps wwwroot/js folder.
Those files got generated as part of a build script in the .csproj, so we'll need to remove that and copy it to our razor class libraries .csproj instead.
They should now look like the following
Web Assembly App:
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly"> <PropertyGroup> <TargetFramework>net5.0</TargetFramework> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="5.0.10" /> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="5.0.10" PrivateAssets="all" /> <PackageReference Include="System.Net.Http.Json" Version="5.0.0" /> </ItemGroup> </Project>
Razor Class Library:
<Project Sdk="Microsoft.NET.Sdk.Razor"> <PropertyGroup> <TargetFramework>net5.0</TargetFramework> </PropertyGroup> <ItemGroup> <SupportedPlatform Include="browser" /> </ItemGroup> <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="5.0.10" /> </ItemGroup> <ItemGroup> <Folder Include="wwwroot\" /> </ItemGroup> <Target Name="PreBuild" BeforeTargets="PreBuildEvent"> <Exec Command="npm run build" WorkingDirectory="sourceJS" /> </Target> </Project>
If we build the solution now, we'll see that Snowpack generates the files in our component library.
well need to add a using statement so it recognises the component. We have the control on more that one page, so we'll add it to the _Imports.razor
When we build now we should get no errors or warnings. So lets run the app.
We get an error. Checking the console:
we can see that it's failed to load our index.js file. The line it's complaining about is
var module = await JSRuntime.InvokeAsync<IJSObjectReference>( "import", "/js/index.js");
This worked fine when it was in the Web Assembly App. But that is because it's the Web Assembly App that is actually doing the executing. Our component library, and any others, are loaded into the web assembly apps space. The contents of our class libraries wwwroot folder get placed in a special folder of the web assembly app so that we need to prepend some extra path details in the format of './_content/[COMPONENT_LIBRARY_NAME]'
So as our Component library name is MyComponentLibrary the line above now becomes
var module = await JSRuntime.InvokeAsync<IJSObjectReference>( "import", "./_content/MyComponentLibrary/js/index.js");
Now if you run the app it will pick up our index.js file and we'll get our component being displayed again.
I hope this series has been useful.