Use Tailwind's new JIT mode when developing Blazor applications
Tailwind 3 shipped with an all new build process, previously referred to as JIT mode.
The gist is that you kick off Tailwind in watch
mode and it sits there, keeping an eye on your html, JS and other
template files.
Then, as you start to use Tailwind’s classes in your template files (Razor components in our case)…
<div class="p-4">
A little bit of padding...
</div>
…Tailwind kicks in and rebuilds a static CSS file with the styles you’re using.
This is a handy way to make sure your CSS file only has definitions for the styles you’re actually using, and means you don’t have to run another process to trim all the Tailwind styles you’re not using at a later point.
Running Tailwind 3
If you’re using a JS framework like React, Vue etc. then you easily configure TailwindCSS to run as part of the normal dev process.
For example, with React, you can run npm run start
as you would normally (to launch your app in dev mode) and Tailwind
will kick in, keeping watch over your app and rebuilding the CSS every time you make changes.
Alternatively, if you’re not using one of those JS frameworks you can use the Tailwind CLI to kick off the watch
process instead.
npx tailwindcss -i ./src/input.css -o ./dist/output.css --watch
Here we’re asking Tailwind to take input.css
and transform it to dist/output.css
.
--watch
ensures this process will keep running, and react every time a change is detected.
This second approach will work for your Blazor projects, you just have to run the Tailwind CLI and keep it running when you’re working on your app.
Introducing Tailwind.Extensions.AspNetCore
In the end though, it would be a lot nicer if you could just launch your Blazor app normally, and have Tailwind run in the background, without having to launch it yourself every time.
And so a new NuGet package is born!
Tailwind.Extensions.AspNetCore
This package gives you a way to seamlessly run Tailwind in watch mode as part of your usual process (
using dotnet watch run
or your IDE).
It works nicely with Hot Reload too, meaning you can kick off your Blazor project with Hot Reload enabled, make changes and see those changes reflected in your browser (with one caveat, which I’ll get to).
Here’s how to get it working with a .NET 6 Blazor Server app (it also works for Blazor WASM apps that are ASP.NET Core hosted).
Set up Tailwind 3
First you need to install Tailwind, as normal, in the root of your project.
npm install -D tailwindcss cross-env
npx tailwindcss init
We’re installing Tailwind and also a handy little library called cross-env which makes sure we can launch processes on both windows and linux.
The second command creates the default tailwind.config.js
file.
tailwind.config.js
module.exports = {
content: [],
theme: {
extend: {},
},
plugins: [],
}
Now you’ll want to update that file’s content
array, to tell it which files Tailwind should keep an eye on.
module.exports = {
content: ["**/*.razor", "**/*.cshtml", "**/*.html"],
theme: {
extend: {},
},
plugins: [],
}
Tailwind needs a stylesheet to start off with (its input file) so you’ll need to create that.
Styles\input.css
@tailwind base;
@tailwind components;
@tailwind utilities;
Finally we need to set up a script in package.json
to actually kick off the Tailwind process.
Update package.json
to add this script.
"scripts": {
"tailwind": "cross-env NODE_ENV=development ./node_modules/tailwindcss/lib/cli.js -i ./Styles/input.css -o ./wwwroot/css/output.css --watch"
},
This script will launch Tailwind, take the input stylesheet we created earlier, and create a static Tailwind CSS file
in wwwroot/css/output.css
Use Tailwind.Extensions.AspNetCore to launch Tailwind’s JIT process
Now the fun bit :)
Add a reference to the Nuget package.
dotnet add package Tailwind.Extensions.AspNetCore --version 1.0.0-beta2
Then head over to Program.cs
and add this code, somewhere before app.Run()
using Tailwind; // add this using statement too
...
if (app.Environment.IsDevelopment())
{
app.RunTailwind("tailwind", "./");
}
The two arguments here are the name of the npm script to run, and the working directory in which to execute the script.
With that, you should now be able to launch your app via dotnet watch run
and see the node process kick in every time
you make changes to your components and/or input.css
file.
Hot Reload Caveat
One thing to note, Hot Reload in Visual Studio is sometimes a little hit and miss.
It seems to work better via dotnet watch
at the moment (from my testing at least).
This isn’t specific to Tailwind or this integration, but rather an issue whereby hot reload doesn’t pick up CSS stylesheet changes when working on an ASP.NET Core hosted Blazor application.
This appears to be a known limitation of the current Hot Reload implementation for Visual Studio 2022.
There’s an open Visual Studio feedback item about it: Hot Reload For CSS Not Working With Blazor WebAssembly Hosted.
If you find this is an issue you may prefer to launch your app via dotnet watch
instead.
Next steps and links
Check out the source code on Github.
There you’ll also find a handy demo Blazor Server app .
The package is available as a pre-release build via NuGet.