8000 Fix Hot Reload profile detection for web apps (#48909) · dotnet/sdk@030cf92 · GitHub
[go: up one dir, main page]

Skip to content

Commit 030cf92

Browse files
authored
Fix Hot Reload profile detection for web apps (#48909)
1 parent 7f4eb8d commit 030cf92

File tree

17 files changed

+204
-88
lines changed

17 files changed

+204
-88
lines changed

src/BuiltInTools/dotnet-watch/Browser/BrowserConnector.cs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ private static ProjectKey GetProjectKey(ProjectGraphNode projectNode)
6363
ProcessSpec processSpec,
6464
EnvironmentVariablesBuilder environmentBuilder,
6565
ProjectOptions projectOptions,
66+
HotReloadProfile profile,
6667
CancellationToken cancellationToken)
6768
{
6869
BrowserRefreshServer? server;
@@ -75,7 +76,7 @@ private static ProjectKey GetProjectKey(ProjectGraphNode projectNode)
7576
hasExistingServer = _servers.TryGetValue(key, out server);
7677
if (!hasExistingServer)
7778
{
78-
server = IsServerSupported(projectNode) ? new BrowserRefreshServer(context.EnvironmentOptions, context.Reporter) : null;
79+
server = IsServerSupported(projectNode, profile) ? new BrowserRefreshServer(context.EnvironmentOptions, context.Reporter) : null;
7980
_servers.Add(key, server);
8081
}
8182
}
@@ -271,36 +272,31 @@ private bool CanLaunchBrowser(DotNetWatchContext context, ProjectGraphNode proje
271272
return true;
272273
}
273274

274-
public bool IsServerSupported(ProjectGraphNode projectNode)
275+
public bool IsServerSupported(ProjectGraphNode projectNode, HotReloadProfile profile)
275276
{
276277
if (context.EnvironmentOptions.SuppressBrowserRefresh)
277278
{
279+
context.Reporter.Report(MessageDescriptor.SkippingConfiguringBrowserRefresh_SuppressedViaEnvironmentVariable.ToErrorWhen(profile.RequiresBrowserRefresh), EnvironmentVariables.SuppressBrowserRefresh);
278280
return false;
279281
}
280282

281283
if (!projectNode.IsNetCoreApp(minVersion: s_minimumSupportedVersion))
282284
{
283-
context.Reporter.Warn(
284-
"Skipping configuring browser-refresh middleware since the target framework version is not supported." +
285-
" For more information see 'https://aka.ms/dotnet/watch/unsupported-tfm'.");
286-
285+
context.Reporter.Report(MessageDescriptor.SkippingConfiguringBrowserRefresh_TargetFrameworkNotSupported.ToErrorWhen(profile.RequiresBrowserRefresh));
287286
return false;
288287
}
289288

290-
if (!IsWebApp(projectNode))
289+
// We only want to enable browser refresh if this is a WebApp (ASP.NET Core / Blazor app).
290+
if (!projectNode.IsWebApp())
291291
{
292-
context.Reporter.Verbose("Skipping configuring browser-refresh middleware since this is not a webapp.");
292+
context.Reporter.Report(MessageDescriptor.SkippingConfiguringBrowserRefresh_NotWebApp.ToErrorWhen(profile.RequiresBrowserRefresh));
293293
return false;
294294
}
295295

296296
context.Reporter.Report(MessageDescriptor.ConfiguredToUseBrowserRefresh);
297297
return true;
298298
}
299299

300-
// We only want to enable browser refresh if this is a WebApp (ASP.NET Core / Blazor app).
301-
private static bool IsWebApp(ProjectGraphNode projectNode)
302-
=> projectNode.GetCapabilities().Any(value => value is "AspNetCore" or "WebAssembly");
303-
304300
private LaunchSettingsProfile GetLaunchProfile(ProjectOptions projectOptions)
305301
{
306302
var projectDirectory = Path.GetDirectoryName(projectOptions.ProjectPath);

src/BuiltInTools/dotnet-watch/DotNetWatcher.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public override async Task WatchAsync(CancellationToken shutdownCancellationToke
6262
};
6363

6464
var browserRefreshServer = (projectRootNode != null)
65-
? await browserConnector.GetOrCreateBrowserRefreshServerAsync(projectRootNode, processSpec, environmentBuilder, Context.RootProjectOptions, shutdownCancellationToken)
65+
? await browserConnector.GetOrCreateBrowserRefreshServerAsync(projectRootNode, processSpec, environmentBuilder, Context.RootProjectOptions, HotReloadProfile.Default, shutdownCancellationToken)
6666
: null;
6767

6868
environmentBuilder.SetProcessEnvironmentVariables(processSpec);

src/BuiltInTools/dotnet-watch/HotReload/CompilationHandler.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,21 @@ public async ValueTask StartSessionAsync(CancellationToken cancellationToken)
102102
_reporter.Report(MessageDescriptor.HotReloadSessionStarted);
103103
}
104104

105-
private static DeltaApplier CreateDeltaApplier(HotReloadProfile profile, ProjectGraphNode project, BrowserRefreshServer? browserRefreshServer, IReporter processReporter)
106-
=> profile switch
105+
private DeltaApplier? CreateDeltaApplier(HotReloadProfile profile, ProjectGraphNode project, BrowserRefreshServer? browserRefreshServer, IReporter processReporter)
106+
{
107+
if (browserRefreshServer == null && profile.RequiresBrowserRefresh)
108+
{
109+
// error has been reported earlier
110+
return null;
111+
}
112+
113+
return profile switch
107114
{
108115
HotReloadProfile.BlazorWebAssembly => new BlazorWebAssemblyDeltaApplier(processReporter, browserRefreshServer!, project),
109116
HotReloadProfile.BlazorHosted => new BlazorWebAssemblyHostedDeltaApplier(processReporter, browserRefreshServer!, project),
110117
_ => new DefaultDeltaApplier(processReporter),
111118
};
119+
}
112120

113121
public async Task<RunningProject?> TrackRunningProjectAsync(
114122
ProjectGraphNode projectNode,
10000 @@ -125,6 +133,12 @@ private static DeltaApplier CreateDeltaApplier(HotReloadProfile profile, Project
125133
var projectPath = projectNode.ProjectInstance.FullPath;
126134

127135
var deltaApplier = CreateDeltaApplier(profile, projectNode, browserRefreshServer, processReporter);
136+
if (deltaApplier == null)
137+
{
138+
// error already reported
139+
return null;
140+
}
141+
128142
var processExitedSource = new CancellationTokenSource();
129143
var processCommunicationCancellationSource = CancellationTokenSource.CreateLinkedTokenSource(processExitedSource.Token, cancellationToken);
130144

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
namespace Microsoft.DotNet.Watch
4+
namespace Microsoft.DotNet.Watch;
5+
6+
internal enum HotReloadProfile
57
{
6-
internal enum HotReloadProfile
7-
{
8-
Default,
8+
Default,
9+
10+
/// <summary>
11+
/// Blazor WebAssembly app
12+
/// </summary>
13+
BlazorWebAssembly,
914

10-
/// <summary>
11-
/// Blazor WebAssembly app
12-
/// </summary>
13-
BlazorWebAssembly,
15+
/// <summary>
16+
/// Blazor WebAssembly app hosted by an ASP.NET Core app.
17+
/// </summary>
18+
BlazorHosted,
19+
}
1420

15-
/// <summary>
16-
/// Blazor WebAssembly app hosted by an ASP.NET Core app.
17-
/// </summary>
18-
BlazorHosted,
21+
internal static class HotReloadProfileExtensions
22+
{
23+
extension(HotReloadProfile profile)
24+
{
25+
public bool RequiresBrowserRefresh
26+
=> profile is HotReloadProfile.BlazorWebAssembly or HotReloadProfile.BlazorHosted;
1927
}
2028
}

src/BuiltInTools/dotnet-watch/HotReload/HotReloadProfileReader.cs

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,44 +11,48 @@ internal static class HotReloadProfileReader
1111
{
1212
public static HotReloadProfile InferHotReloadProfile(ProjectGraphNode projectNode, IReporter reporter)
1313
{
14-
var queue = new Queue<ProjectGraphNode>();
15-
queue.Enqueue(projectNode);
16-
17-
ProjectInstance? aspnetCoreProject = null;
14+
if (projectNode.IsWebApp())
15+
{
16+
var queue = new Queue<ProjectGraphNode>();
17+
queue.Enqueue(projectNode);
1818

19-
var visited = new HashSet<ProjectGraphNode>();
19+
ProjectInstance? aspnetCoreProject = null;
2020

21-
while (queue.Count > 0)
22-
{
23-
var currentNode = queue.Dequeue();
24-
var projectCapability = currentNode.ProjectInstance.GetItems("ProjectCapability");
21+
var visited = new HashSet<ProjectGraphNode>();
2522

26-
foreach (var item in projectCapability)
23+
while (queue.Count > 0)
2724
{
28-
if (item.EvaluatedInclude == "AspNetCore")
29-
{
30-
aspnetCoreProject = currentNode.ProjectInstance;
31-
break;
32-
}
33-
else if (item.EvaluatedInclude == "WebAssembly")
25+
var currentNode = queue.Dequeue();
26+
var projectCapability = currentNode.ProjectInstance.GetItems("ProjectCapability");
27+
28+
foreach (var item in projectCapability)
3429
{
35-
// We saw a previous project that was AspNetCore. This must he a blazor hosted app.
36-
if (aspnetCoreProject is not null && aspnetCoreProject != currentNode.ProjectInstance)
30+
if (item.EvaluatedInclude == "AspNetCore")
3731
{
38-
reporter.Verbose($"HotReloadProfile: BlazorHosted. {aspnetCoreProject.FullPath} references BlazorWebAssembly project {currentNode.ProjectInstance.FullPath}.", emoji: "🔥");
39-
return HotReloadProfile.BlazorHosted;
32+
aspnetCoreProject = currentNode.ProjectInstance;
33+
break;
4034
}
4135

42-
reporter.Verbose("HotReloadProfile: BlazorWebAssembly.", emoji: "🔥");
43-
return HotReloadProfile.BlazorWebAssembly;
36+
if (item.EvaluatedInclude == "WebAssembly")
37+
{
38+
// We saw a previous project that was AspNetCore. This must he a blazor hosted app.
39+
if (aspnetCoreProject is not null && aspnetCoreProject != currentNode.ProjectInstance)
40+
{
41+
reporter.Verbose($"HotReloadProfile: BlazorHosted. {aspnetCoreProject.FullPath} references BlazorWebAssembly project {currentNode.ProjectInstance.FullPath}.", emoji: "🔥");
42+
return HotReloadProfile.BlazorHosted;
43+
}
44+
45+
reporter.Verbose("HotReloadProfile: BlazorWebAssembly.", emoji: "🔥");
46+
return HotReloadProfile.BlazorWebAssembly;
47+
}
4448
}
45-
}
4649

47-
foreach (var project in currentNode.ProjectReferences)
48-
{
49-
if (visited.Add(project))
50+
foreach (var project in currentNode.ProjectReferences)
5051
{
51-
queue.Enqueue(project);
52+
if (visited.Add(project))
53+
{
54+
queue.Enqueue(project);
55+
}
5256
}
5357
}
5458
}

src/BuiltInTools/dotnet-watch/HotReload/ProjectLauncher.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public EnvironmentOptions EnvironmentOptions
9494
}
9595
}
9696

97-
var browserRefreshServer = await browserConnector.GetOrCreateBrowserRefreshServerAsync(projectNode, processSpec, environmentBuilder, projectOptions, cancellationToken);
97+
var browserRefreshServer = await browserConnector.GetOrCreateBrowserRefreshServerAsync(projectNode, processSpec, environmentBuilder, projectOptions, profile, cancellationToken);
9898

9999
var arguments = new List<string>()
100100
{

0 commit comments

Comments
 (0)
0