I'm a big fan of VS Code and love using it to write all types of apps I can. Also, I like working with C# and wanted to play a bit with Blazor recently. Combining both of these interests, I decided to write a small project in Blazor, but using VS Code instead of typical Visual Studio approach. It also forced me to learn dotnet CLI a bit more (not as much as I thought at the beginning, though 😄). In this post, I'll describe general project configuration which includes:
- Creating a new Blazor Web App solution & project
- Adding a custom, "Shared", project to the solution
- VS Code setup
- Debugging in VS Code (including Hot Reload)
- Adding Bootstrap and Tailwind to the project
Maybe, one day, I'll dive a bit more into the project implementation, but for now, it's gonna be just the environment setup 😉
Creating the project
As mentioned, I wanted to learn a bit of dotnet CLI, so we'll create the solution and add needed projects using command line.
The goal is to have a solution with the default Blazor Web App projects + additional "Shared" project that can contain, for example, business logic, classes common for backend and frontend, etc.
Empty solution and Blazor Web App project
To create an empty solution, run
dotnet new sln -o MyCoolProject
And then run
dotnet new blazor -int Auto --empty -n MyCoolProject
to create a Blazor Web App project.
Quick explanation of the arguments:
-
blazor
- creates a Blazor Web App -
-int Auto
- sets interactivity mode of the Blazor project to Auto which allows the project to automatically switch between server-side and client-side rendering based on the context -
--empty
- project will be empty, without any predefined pages/components -
-n MyCoolProject
- sets the name of the project
"Shared" class library
The "Shared" project is a simple class library, so it can be created by running
dotnet new classlib -o MyCoolProject.Shared
Connecting things - adding to solution and referencing
We have all the projects, but not linked to the solution. Let's fix that with
dotnet sln add .\MyCoolProject\MyCoolProject.csproj .\MyCoolProject.Client\MyCoolProject.Client.csproj .\MyCoolProject.Shared\MyCoolProject.Shared.csproj
And then reference "Shared" project in both other projects with
dotnet add .\MyCoolProject\MyCoolProject.csproj reference .\MyCoolProject.Shared\MyCoolProject.Shared.csproj
dotnet add .\MyCoolProject.Client\MyCoolProject.Client.csproj reference .\MyCoolProject.Shared\MyCoolProject.Shared.csproj
It's nearly done. However, to make the Shared code actually visible in the other ones, we also need to update global imports. To do that, add
@using MyCoolProject.Shared
at the end of
MyCoolProject\Components\_Imports.razor
MyCoolProject.Client\_Imports.razor
Done? Try
dotnet run
and see if things work.
VS Code setup
For the previous steps we didn't even have to open VS Code. Time to change that.
First - extensions. Probably the most important one is C# Dev Kit. You can read its description yourself, but, in essence, it makes VS Code more IDE-like for C# compared to being just a text editor. You might also look into IntelliCode for C# DevKit if you feel like normal code completion might be not enough.
As we're already playing with the editor configuration, let's do one more thing - enable Hot Reload. As it's an experimental feature, it's not enabled by default. Simply, open VS Code settings (CTRL + ,
), search for "hot-reload" and check this setting:
Debugging
At that point, we should be able to run and debug the code from VS Code - ideally, just press F5 and it should work. If not, click "Run and debug", select C#, and then something with "default configuration". At worst, restart VS Code (to be sure, really close and open it again, not just reload the window via the command palette).
Now let's try actual debugging with a breakpoint. Due to the project config with Auto, remember about @rendermode InteractiveAuto
at the top of the Home.razor
file:
@page "/"
@rendermode InteractiveAuto
<h3>Simple Counter</h3>
<p>Current value: <strong>@counterValue</strong></p>
<button @onclick="IncrementCounter">Increment</button>
@code {
private int counterValue = 0;
private void IncrementCounter()
{
counterValue++;
}
}
Place a breakpoint in the IncrementCounter
method, run the app in debug mode, and, hopefully, it will be hit when you press the button to increase the counter.
❗ If the counter doesn't work and you see an error in the DevTools console about the Home component not being found, move it from the MyCoolProject/Components/Pages
directory to MyCoolProject.Client/Components
❗Here are some docs about it.
Hot Reload
There's not much to say about Hot Reload - after enabling the setting in VS Code, it should work.
To test it, run the app, change something in the source file, save it, and refresh the page. Changes should be visible instantly.
CSS library
We are nearly done with the config! Let's sprinkle our project with some CSS library and we're good to go.
I usually use Bootstrap and I started with setting up the project to use it. Then, I recalled I wanted to give Tailwind CSS a shot at some point, so that's the CSS library of choice here. As I, however, set up Bootstrap, here's a quick guide for it.
Bootstrap
Managing simple libraries in Blazor projects is the easiest when using LibMan. As this series is focused on doing stuff manually, I'll do the same with LibMan. Luckily, there's a nice CLI tool for it.
Docs are super clear and to the point, so I won't write everything again here, but in short:
-
install LibMan globally with
dotnet tool install -g Microsoft.Web.LibraryManager.Cli
-
initialize it in the current project with
libman init -p unpkg
in
.Client
project folder (why unpkg?) -
add Boostrap 5 with
libman install bootstrap -d wwwroot/lib/bootstrap
If you're wondering why we didn't give any default destination - unfortunately, LibMan doesn't put a new library in the dedicated folder anyway 🤷
-
you'll probably need Popper for some scripts to work, so add it with
libman install "@popperjs/core" -d wwwroot/lib/popper
-
link CSS/HTML in
MyCoolProject/Components/Pages/App.razor
:
<head> ... <link rel="stylesheet" href="lib/bootstrap/dist/css/bootstrap.min.css" /> ... </head> <body> ... <script src="lib/popper/dist/umd/popper.min.js"></script> <script src="lib/bootstrap/dist/js/bootstrap.min.js"></script> </body>
that should make most of the Bootstrap stuff work. You will still have problems with, for example, tooltips, though. Then check this SO answer
I haven't checked the whole integration thoroughly, so treat the above steps just as a starter 😊
Tailwind
Tailwind can be summarized as a set of utility CSS classes you can use to style your HTML. They are similar to Bootstrap p-4
, mb-3
, d-flex
etc. but way more powerful. Another point worth noting from a configuration point of view is its build process - there is a Tailwind tool that scans your source files, looks for Tailwind CSS class names, and includes them in the final CSS file you link to your main HTML. That's it in terms of theory - let's actually add Tailwind to our Blazor project. I've followed Chris Sainty's blog post on that.
First things first, we'll need the mentioned Tailwind tool for creating the output CSS. Install it globally with
npm install -g tailwindcss
Then we need a main config file for Tailwind. To create it, go to the root directory of the project and run
npx tailwindcss init
And then, adjust content
field in the created tailwind.config.js
to be:
content: [
'./MyCoolProject/**/*.{razor,html}',
'./MyCoolProject.Client/**/*.{razor,html}',
],
It tells Tailwind which files to watch for the CSS classes.
Then we need the main CSS files to be processed by Tailwind. We'll also include default Tailwind classes and styles there. We can use the existing MyCoolProject\wwwroot\app.css
file for that. Just add:
@tailwind base;
@tailwind components;
@tailwind utilities;
at the top and that should do the trick.
Using CLI, we should now tell Tailwind which file to process and where to put the final CSS that we'll link in the HTML. Our input will be the mentioned app.css
file, and we'll output the final CSS to MyCoolProject\wwwroot\app-compiled.css
. The command is:
npx tailwindcss -i .\MyCoolProject\wwwroot\app.css -o .\MyCoolProject\wwwroot\app-compiled.css --watch
Due to the --watch
switch it also automatically rebuilds the output after any changes in the input file are detected.
To finish linking Tailwind to out app, go to MyCoolProject\Components\App.razor
and update one of the <link>
tags which contains reference to app.css
and change it to app-compiled.css
, i.e.:
<link rel="stylesheet" href="app-compiled.css" />
To test if things work, you can open MyCoolProject.Client\Components\Home.razor
and add somewhere
<h1 class="text-3xl font-bold underline">
Hello world!
</h1>
Then launch the app (F5).
Summary
In the post, I've very briefly described how to set up a dev environment for developing Blazor Web App using VS Code. We created solution, projects and linked them properly using dotnet CLI. Then we added the most important extensions to VS Code and updated it settings to enable Hot Reload. To finish the configuration, we added CSS library (Tailwind).
It's very much not in-depth post, but I hope it gives a general idea of how to do things 😊 Blazor is quite a new thing for me, so comments and questions are more than welcome.
Thanks for reading! ❤️
PS
I've been writing this post over quite some time (motivation, time & stuff), so if something doesn't work anymore, let me know!