aspnetcore/src/Tools/dotnet-watch
Pranav K b34c5ddd5f
Prevent dotnet-watch script injection staleness (#27778)
The browser refresh mechansim used by dotnet-watch and VS modifies HTML content. The modified content includes
a script block that has a WebSocket url that changes for each new execution of dotnet watch run (not rebuilds, but watch itself).
HTML content can come from views or static html files on disk. For the latter, ASP.NET Core participates in browser caching by sending (and invalidating) etag headers.

One way to fix this problem is remove or modify the etag headers. The risk here is that might cause differences in behavior in development users may come to rely on that are unavailable in production. This change instead modifies the HTML content so the output is always consistent and consequently safe to cache. The dynamic content is served separately by the injected middleware.

This change fixes the issue of multiple instances of dotnet-watch. While this issue may crop up if you alternate between dotnet run and dotnet watch run but we haven't seen this being an issue as yet.

Fixes #27548

Summary
Running dotnet watch run multiple times in Blazor WASM apps (or any app that serves static html files) can produce console errors and prevent the browser refresh feature from working. Given that we've been telling our users to use dotnet watch run as their primary way to work outside of VS, it's likely more users would run in this.

Customer impact
A hard browser refresh (Ctrl + R) is needed to get the refresh behavior to work.

Regression
No. This has existed since the feature was introduced we did not get reports of it

Risk
Low. The fix is isolated to dotnet-watch and VS's browser refresh mechanism which is in preview. The change was tested locally, but if there's a regression or if the change interferes with user's workflow, users have the ability to disable this feature.
2020-11-13 14:25:47 -08:00
..
BrowserRefresh Prevent dotnet-watch script injection staleness (#27778) 2020-11-13 14:25:47 -08:00
src
test
README.md

README.md

dotnet-watch

dotnet-watch is a file watcher for dotnet that restarts the specified application when changes in the source code are detected.

How To Use

The command must be executed in the directory that contains the project to be watched.

Usage: dotnet watch [options] [[--] <args>...]

Options:
  -?|-h|--help  Show help information
  -q|--quiet    Suppresses all output except warnings and errors
  -v|--verbose  Show verbose output

Add watch after dotnet and before the command arguments that you want to run:

What you want to run Dotnet watch command
dotnet run dotnet watch run
dotnet run --arg1 value1 dotnet watch run --arg1 value
dotnet run --framework net451 -- --arg1 value1 dotnet watch run --framework net451 -- --arg1 value1
dotnet test dotnet watch test

Environment variables

Some configuration options can be passed to dotnet watch through environment variables. The available variables are:

Variable Effect
DOTNET_USE_POLLING_FILE_WATCHER If set to "1" or "true", dotnet watch will use a polling file watcher instead of CoreFx's FileSystemWatcher. Used when watching files on network shares or Docker mounted volumes.
DOTNET_WATCH_SUPPRESS_MSBUILD_INCREMENTALISM By default, dotnet watch optimizes the build by avoiding certain operations such as running restore or re-evaluating the set of watched files on every file change. If set to "1" or "true", these optimizations are disabled.
DOTNET_WATCH_SUPPRESS_LAUNCH_BROWSER dotnet watch run will attempt to launch browsers for web apps with launchBrowser configured in launchSettings.json. If set to "1" or "true", this behavior is suppressed.
DOTNET_WATCH_SUPPRESS_MSBUILD_INCREMENTALISM dotnet watch run will attempt to refresh browsers when it detects file changes. If set to "1" or "true", this behavior is suppressed. This behavior is also suppressed if DOTNET_WATCH_SUPPRESS_LAUNCH_BROWSER is set.

MSBuild

dotnet-watch can be configured from the MSBuild project file being watched.

Watch items

dotnet-watch will watch all items in the Watch item group. By default, this group inclues all items in Compile and EmbeddedResource.

More items can be added to watch in a project file by adding items to 'Watch'.

<ItemGroup>
    <!-- extends watching group to include *.js files -->
    <Watch Include="**\*.js" Exclude="node_modules\**\*.js;$(DefaultExcludes)" />
</ItemGroup>

dotnet-watch will ignore Compile and EmbeddedResource items with the Watch="false" attribute.

Example:

<ItemGroup>
    <!-- exclude Generated.cs from dotnet-watch -->
    <Compile Update="Generated.cs" Watch="false" />
    <!-- exclude Strings.resx from dotnet-watch -->
    <EmbeddedResource Update="Strings.resx" Watch="false" />
</ItemGroup>

Project References

By default, dotnet-watch will scan the entire graph of project references and watch all files within those projects.

dotnet-watch will ignore project references with the Watch="false" attribute.

<ItemGroup>
  <ProjectReference Include="..\ClassLibrary1\ClassLibrary1.csproj" Watch="false" />
</ItemGroup>

Advanced configuration

dotnet-watch performs a design-time build to find items to watch. When this build is run, dotnet-watch will set the property DotNetWatchBuild=true.

Example:

  <ItemGroup Condition="'$(DotNetWatchBuild)'=='true'">
    <!-- only included in the project when dotnet-watch is running -->
  </ItemGroup>