LibSassBuilder
LibSassBuilder copied to clipboard
How to use with Hot Reload?
Hello, and thanks for this wonderful tool.
Currently, I'm working with a lot of SCSS files, and after each edit I ALT+TAB
out to my Terminal and enter lsb
. Then lsb transforms all my *.scss files into *.css. dotnet will pick up these file changes, and then the gui is refreshed with new and fancy styles.
Is it possible to watch for changes in *.scss files and run lsb upon save (a change in scss-file)? It's getting tedious to run lsb upon each edit...
I'm using 6.0.0-rc.1.21452.15.
This would be great feature for Blazor
Hi there - yes the *.scss
files are watched by default with this NuGet package installed in your .NET project.
You shouldn't have to use (or even install) the CLI tool for this purpose.
@johan-v-r I do not know if I understood you correctly. I can run my app, edit sass/scss file and this wil be automatically converted to css ? I tried this with blazor server on .Net 5 and It was not working.
If you run your app with dotnet watch
then yes it will rebuild when you save a Sass file.
If you don't come right, could you create a sample project so I can replicate & test?
@johan-v-r Hello, on my side with dotnet watch
it's working but it do a full rebuild on each change on .scss
files is that normal ? if yes I would be nice to to get it to avoid rebuild each time.
watch : File changed: /xxxxxx/Component.razor.scss.
watch : Exited
watch : Building...
<PackageReference Include="LibSassBuilder" Version="1.6.4" />
Has someone managed to use dotnet watch
with this plugin, without full rebuild on each change?
Struggling to get this working as well.
Just in case you're not aware @johan-v-r this is Hot Reload we're talking about (not auto-builds) - specifically .NET/Blazor Watch's handling of Browser resource hot reloads:
info: Microsoft.Hosting.Lifetime[0]
Content root path: /Users/.../Personal Projects/BlazorTutorial/
watch : File changed: /Users/.../Personal Projects/BlazorTutorial/Shared/NavMenu.razor.css.
watch : Hot reload of scoped css succeeded
That is what happens if you change a single CSS file and is what is referred to as a hot-reload - the resource/content file is updated on the server and re-sent to the browser without any full project build occuring.
On the otherhand, here is what happens if I do the same to a SCSS file:
info: Microsoft.Hosting.Lifetime[0]
Content root path: /Users/.../Personal Projects/BlazorTutorial/
watch : File changed: /Users/.../Personal Projects/BlazorTutorial/Shared/MainLayout.razor.scss.
watch : Do you want to restart your app - Yes (y) / No (n) / Always (a) / Never (v)?
It seems like your plugin enforces some strict watch
rules because ignoring changes to SCSS files does not work (same output as above):
<ItemGroup>
<None Include="**/*.scss" />
</ItemGroup>
I don't know too much about MSBuild and its targets but is it possible to trigger this package's build without requiring a full watch/build on SCSS files?
As far as I can tell when hot reload (dotnet watch without args) detects a file change the following happens:
- if the file is a static file (the
Watch
item has aStaticWebAssetPath
metadata, e.g. allContent
files underwwwroot/
) then reload the browser window - if the file extension is
.razor.css
or.cshtml.css
then rebuild scoped css and apply changes without restarting the app - if the file extension is
.cs
or.razor
or.cshtml
then use Edit&Continue on the c# source to apply changes (if it's a supported edit) - everything else is considered a "rude" edit (i.e. prompt to restart the entire app)
All of this is more or less hardwired in dotnet-watch, adding sass as Watch
items simply won't work, a change is always considered a rude edit. However a separate dotnet-watch instance can be configured to handle sass like this:
Add this to your main csproj:
<ItemGroup>
<!-- exclude sass files from main dotnet watch -->
<SassFile Update="@(SassFile)" Watch="false" />
</ItemGroup>
<!-- expose sass source files to helper project -->
<Target Name="CollectSassItems" Outputs="@(SassFile)" />
Create a new proj file e.g. Sass.proj
next to your csproj or sln or wherever. This is a helper project that configures dotnet-watch to handle sass only. Unfortunately dotnet-watch cannot handle different project configurations, a separate project is needed.
<Project DefaultTargets="SassBuild">
<PropertyGroup>
<CustomCollectWatchItems>$(CustomCollectWatchItems);SassCollectWatchItems</CustomCollectWatchItems>
<!-- this is needed or else the watch process fails with NRE -->
<TargetFramework>net6.0</TargetFramework>
<!-- Path to your project here with the sass files to compile -->
<SassProject>Path\To\YourProjectThatHasSassToBuild.csproj</SassProject>
</PropertyGroup>
<!-- collect sass files from main project -->
<Target Name="SassCollectWatchItems">
<MSBuild Projects="$(SassProject)" Targets="CollectSassItems" BuildInParallel="true">
<Output TaskParameter="TargetOutputs" ItemName="Watch" />
</MSBuild>
</Target>
<!-- invoke sass compilation in the main project -->
<Target Name="SassBuild">
<MSBuild Projects="$(SassProject)" Targets="LibSass_DetermineBuildNeeded;LibSass_BuildArgsFromFileList;LibSass_Build" BuildInParallel="true" />
</Target>
<Import Project="$(MSBuildExtensionsPath)\Microsoft.Common.targets"/>
</Project>
then finally run
dotnet watch --project Sass.proj msbuild
This will run the LibSass pipeline for every changed sass, then the main dotnet watch
will pick up the changed sass output.
I tried @bachratyg's workaround, but dotnet watch
still reloaded my whole application on each scss
-file change.
To make dotnet watch
really ignore scss
-file changes, not only you must use
<ItemGroup>
<!-- exclude sass files from main dotnet watch -->
<SassFile Update="@(SassFile)" Watch="false" />
</ItemGroup>
but also add the same for Content
elements. So the resulting edit is:
<ItemGroup>
<!-- exclude sass files from main dotnet watch -->
<SassFile Update="@(SassFile)" Watch="false" />
<!-- tell main dotnet watch to really ignore scss files -->
<Content Update="@(SassFile)" Watch="false" />
</ItemGroup>
Info
LibSassBuilder: 2.0.1 .NET: 6.0
@warappa you may have scss under wwwroot that gets picked up as Content
and triggers a browser refresh on change. Since you probably don't want them published you can simply exclude them:
<Content Remove="wwwroot/**/*.scss" />
@bachratyg You're right, excluding them is actually better 👍
My VS is picking changes in css files automatically, but build of sass files happen only on run, is there a way to force it to compile on save?