Skip to content
This repository has been archived by the owner on Mar 22, 2023. It is now read-only.

How to use with Hot Reload? #31

Open
kabforks opened this issue Sep 17, 2021 · 12 comments
Open

How to use with Hot Reload? #31

kabforks opened this issue Sep 17, 2021 · 12 comments

Comments

@kabforks
Copy link

kabforks commented Sep 17, 2021

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.

@mikart143
Copy link

This would be great feature for Blazor

@johan-v-r
Copy link
Owner

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.

@mikart143
Copy link

@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.

@johan-v-r
Copy link
Owner

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?

@Socolin
Copy link

Socolin commented Nov 15, 2021

@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" />

@nanocortex
Copy link

Has someone managed to use dotnet watch with this plugin, without full rebuild on each change?

@SacredSkull
Copy link

SacredSkull commented Mar 25, 2022

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?

@bachratyg
Copy link

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 a StaticWebAssetPath metadata, e.g. all Content files under wwwroot/) 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.

@warappa
Copy link

warappa commented Jun 18, 2022

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

@bachratyg
Copy link

bachratyg commented Jun 19, 2022

@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" />

@warappa
Copy link

warappa commented Jun 19, 2022

@bachratyg You're right, excluding them is actually better 👍

@dawiduniec
Copy link

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?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants