Blazor, dotnet CLI, VS Code & Tailwind - how to set that up?

Piotr Ładoński - Aug 22 - - Dev Community

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:

  1. Creating a new Blazor Web App solution & project
  2. Adding a custom, "Shared", project to the solution
  3. VS Code setup
  4. Debugging in VS Code (including Hot Reload)
  5. 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
Enter fullscreen mode Exit fullscreen mode

And then run

dotnet new blazor -int Auto --empty -n MyCoolProject
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

at the end of

  • MyCoolProject\Components\_Imports.razor
  • MyCoolProject.Client\_Imports.razor

Done? Try

dotnet run
Enter fullscreen mode Exit fullscreen mode

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:

Screenshot of VS Code Hot Reload 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++;
    }
}
Enter fullscreen mode Exit fullscreen mode

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/ComponentsHere 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

And then, adjust content field in the created tailwind.config.js to be:

content: [
    './MyCoolProject/**/*.{razor,html}',
    './MyCoolProject.Client/**/*.{razor,html}',
],
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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" />
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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!

. . . . . .