At the beginning I'd like to introduce my motivation to create this example. My friends which moved from PHP to .Net stack, were complaining that they had to recompile application every time they made a little change in source code. They said:
"In PHP we've changed a script file, reload a page and I can see my changes. In C# we need to recompile whole application and that's annoying..."
For my that was naturally that I need to recompile ma application. That's the price for high performance. Accidentally I heard from Tomasz Kopacz about dotnet watch and my "little" world has changed. Now I would like to share information about that tool with other developers.
This repository contains ASP.Net Core 2.0 application with dotnet watch tool used in development phase. I hope this tool will increase your productivity.
Setup & run
Setup of dotnet watch tool is super easy. We need to add reference to Microsoft.Dotnet.Watcher.Tools in *.csproj file:
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.DotNet.Watcher.Tools" Version="2.0.0" />
</ItemGroup>
After that we need to restore packages in our project and Voila! Now we can use dotnet watch tool like:
dotnet restore
dotnet watch run
# example output
watch : Started
Hosting environment: Production
Content root path: (...)\dotnet-watch-example\ExampleMvcApp
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.
Now we can make changes in our solution files. Every change will trigger dotnet watch tool and rebuild our application:
watch : Exited with error code 1
watch : File changed: (...)\dotnet-watch-example\ExampleMvcApp\Startup.cs
watch : Started
Hosting environment: Production
Content root path: (...)\dotnet-watch-example\ExampleMvcApp
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.
That's all. Now you can play with my example on your own but remember that every change triggers a build. That results a downtime of our application. Keep in mind that every mistake in code will broke application which will be shut down until you fix bug in code. Example below:
watch : Exited with error code 1
watch : File changed: (...)\dotnet-watch-example\ExampleMvcApp\Startup.cs
watch : Started
Startup.cs(43,18): error CS1001: Identifier expected [(...)\dotnet-watch-example\ExampleMvcApp\ExampleMvcApp.csproj]
Startup.cs(43,18): error CS1002: ; expected [(...)\dotnet-watch-example\ExampleMvcApp\ExampleMvcApp.csproj]
The build failed. Please fix the build errors and run again.
watch : Exited with error code 1
watch : Waiting for a file to change before restarting dotnet...
Tests
Dotnet watch can be used also to trigger application tests if there is any change in code. To achive that we need only setup test with watch tool. Example of execution:
dotnet watch test
watch : Started
Build started, please wait...
Build completed.
Test run for (...)\dotnet-watch-example\ExampleMvcApp.Tests\bin\Debug\netcoreapp2.0\ExampleMvcApp.Tests.dll(.NETCoreApp,Version=v2.0)
Microsoft (R) Test Execution Command Line Tool Version 15.3.0-preview-20170628-02
Copyright (c) Microsoft Corporation. All rights reserved.
Starting test execution, please wait...
[xUnit.net 00:00:01.9710205] Discovering: ExampleMvcApp.Tests
[xUnit.net 00:00:02.0615903] Discovered: ExampleMvcApp.Tests
[xUnit.net 00:00:02.1304412] Starting: ExampleMvcApp.Tests
[xUnit.net 00:00:02.3174366] ExampleMvcApp.Tests.SimpleTest.SimpleTest_WithoutConditions_ShouldPass [FAIL]
[xUnit.net 00:00:02.3186889] Assert.True() Failure
[xUnit.net 00:00:02.3188818] Expected: True
[xUnit.net 00:00:02.3189584] Actual: False
[xUnit.net 00:00:02.3199073] Stack Trace:
[xUnit.net 00:00:02.3212204] (...)\dotnet-watch-example\ExampleMvcApp.Tests\SimpleTest.cs(11,0): at ExampleMvcApp.Tests.SimpleTest.SimpleTest_WithoutConditions_ShouldPass()
[xUnit.net 00:00:02.3342243] Finished: ExampleMvcApp.Tests
Failed ExampleMvcApp.Tests.SimpleTest.SimpleTest_WithoutConditions_ShouldPass
Error Message:
Assert.True() Failure
Expected: True
Actual: False
Stack Trace:
at ExampleMvcApp.Tests.SimpleTest.SimpleTest_WithoutConditions_ShouldPass() in (...)\dotnet-watch-example\ExampleMvcApp.Tests\SimpleTest.cs:line 11
Total tests: 1. Passed: 0. Failed: 1. Skipped: 0.
Test Run Failed.
Test execution time: 3,1153 Seconds
watch : Exited with error code 1
watch : Waiting for a file to change before restarting dotnet...
watch : Started
Build started, please wait...
Build completed.
Test run for (...)\dotnet-watch-example\ExampleMvcApp.Tests\bin\Debug\netcoreapp2.0\ExampleMvcApp.Tests.dll(.NETCoreApp,Version=v2.0)
Microsoft (R) Test Execution Command Line Tool Version 15.3.0-preview-20170628-02
Copyright (c) Microsoft Corporation. All rights reserved.
Starting test execution, please wait...
[xUnit.net 00:00:01.9361049] Discovering: ExampleMvcApp.Tests
[xUnit.net 00:00:02.0139917] Discovered: ExampleMvcApp.Tests
[xUnit.net 00:00:02.0731938] Starting: ExampleMvcApp.Tests
[xUnit.net 00:00:02.2357251] Finished: ExampleMvcApp.Tests
Total tests: 1. Passed: 1. Failed: 0. Skipped: 0.
Test Run Successful.
Test execution time: 2,9806 Seconds
watch : Exited
watch : Waiting for a file to change before restarting dotnet...
Tips
We can extend dotnet watch tool to trigger a rebuild & restart our application not only after change in .cs files but in other kind of files as well. In my opinion very usful is file mask on appsettings. Every change in this file will trigger *dotnet watch. Time needed to restart our application will be shorter that after change in *.cs file becouse we don't need to rebuild the solution. Example of file mask on appsettings file below:
<ItemGroup>
<!-- extends watching group to include .\appsettings*.json files -->
<Watch Include=".\appsettings*.json" />
</ItemGroup>
Summary
To sum up dotnet watch is a very useful tool which will improve your productivity. In my opinion it will be espesially powerful is situation when are developing an application or check something very quickly and we don't want to run Visual Studio.
I hope dotnet watch tool will increase your productivity as it was in my case.
Top comments (5)
I think that in medium project rebuild phase is extremely slow. I can't wait after any code change for a 20-50 seconds to rebuild projects and then run tests. On Go or Node.js it happens almost instantly (1-2 seconds). Why .net core build process is so slow?
I agree that the rebuild time depends on the size of the solution. I wouldn't recommend this for medium/large solutions (50+ projects).
.Net is a compiled language. If I good remember, NodeJS bases on Javascript which is an interpreted language. The comparison between them doesn't make sense.
In the case of Go the situation is different. Go belongs to the compiled languages family. It's hard for me to say why Go is so fast because I've no experience with this programming language.
It could be an interesting experiment to compare build time for the same solution coded in both C# and GO. I can only guess that maybe the vast amount of dependencies in C# (.Net) slows it. But that is just my assumption.
Thank you for your reply. Node.js precompile javascript code before run it.
I think that .Net Core need some more intelligent mechanism than just simple watch(build project and all it's dependencies on source change). TypeScript and Node.js doesn't rebuild all project after one file change in watch mode. It rebuild only changed portion of code.
It will be cool if .Net Core introduced that feature. For example i change ClassA => Some mechanism detect this immediately (like nodemon) => Recompile ClassA => Recompile all referenced code that use ClassA => Patch assembly.
In early days of .Net Core (first bettas) it used another build engine (not old fat MsBuild) and it worked a lot faster than now.
Unfortunately, it isn't that simple. The example that you gave (Typescript and NodeJS) is excellent.
First of all, Typescript files are being transpiled to the ”pure” JavaScript. That process doesn't have to cover all files. Only files that have been changed have to be translated into the new language.
On the other hand, in the compilation process, we are not able to extract and compile only modified files. The compilation has to cover all files to produce a library which is being treated as the comprehensive part of the software.
I think that is the difference which causes that you and I have to wait longer for the build result.
Thanks Rafal for you'r response , but what is the magic behind livesharp.net/ ?