Skip to content

Commit

Permalink
Refresh browser for all transitively referencing projects
Browse files Browse the repository at this point in the history
  • Loading branch information
tmat committed Nov 24, 2024
1 parent ff3f83c commit 6224ed9
Show file tree
Hide file tree
Showing 18 changed files with 497 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ private async ValueTask DisplayResultsAsync(WatchHotReloadService.Updates update
switch (updates.Status)
{
case ModuleUpdateStatus.None:
_reporter.Output("No hot reload changes to apply.");
_reporter.Output("No C# changes to apply.");
break;

case ModuleUpdateStatus.Ready:
Expand Down
61 changes: 41 additions & 20 deletions src/BuiltInTools/dotnet-watch/HotReload/ScopedCssFileHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections;
using System.Diagnostics;
using Microsoft.Build.Graph;
using Microsoft.Build.Framework;
using Microsoft.DotNet.Watcher.Internal;
using Microsoft.Extensions.Tools.Internal;

Expand Down Expand Up @@ -52,41 +53,61 @@ public async ValueTask HandleFileChangesAsync(IReadOnlyList<ChangedFile> files,
}
}

var logger = reporter.IsVerbose ? new[] { new Build.Logging.ConsoleLogger() } : null;
if (!hasApplicableFiles)
{
return;
}

var logger = reporter.IsVerbose ? new[] { new Build.Logging.ConsoleLogger(LoggerVerbosity.Minimal) } : null;

var tasks = projectsToRefresh.Select(async projectNode =>
var buildTasks = projectsToRefresh.Select(projectNode => Task.Run(() =>
{
if (!projectNode.ProjectInstance.DeepCopy().Build(BuildTargetName, logger))
try
{
return false;
if (!projectNode.ProjectInstance.DeepCopy().Build(BuildTargetName, logger))
{
return null;
}
}
if (browserConnector.TryGetRefreshServer(projectNode, out var browserRefreshServer))
catch (Exception e)
{
await HandleBrowserRefresh(browserRefreshServer, projectNode.ProjectInstance.FullPath, cancellationToken);
reporter.Error($"[{projectNode.GetDisplayName()}] Target {BuildTargetName} failed to build: {e}");
return null;
}
return true;
});
return projectNode;
}));

var results = await Task.WhenAll(tasks).WaitAsync(cancellationToken);
var buildResults = await Task.WhenAll(buildTasks).WaitAsync(cancellationToken);

if (hasApplicableFiles)
var browserRefreshTasks = buildResults.Where(p => p != null)!.GetTransitivelyReferencingProjects().Select(async projectNode =>
{
var successfulCount = results.Sum(r => r ? 1 : 0);

if (successfulCount == results.Length)
{
reporter.Output("Hot reload of scoped css succeeded.", emoji: "🔥");
}
else if (successfulCount > 0)
if (browserConnector.TryGetRefreshServer(projectNode, out var browserRefreshServer))
{
reporter.Output($"Hot reload of scoped css partially succeeded: {successfulCount} project(s) out of {results.Length} were updated.", emoji: "🔥");
reporter.Verbose($"[{projectNode.GetDisplayName()}] Refreshing browser.");
await HandleBrowserRefresh(browserRefreshServer, projectNode.ProjectInstance.FullPath, cancellationToken);
}
else
{
reporter.Output("Hot reload of scoped css failed.", emoji: "🔥");
reporter.Verbose($"[{projectNode.GetDisplayName()}] No refresh server.");
}
});

await Task.WhenAll(browserRefreshTasks).WaitAsync(cancellationToken);

var successfulCount = buildResults.Sum(r => r != null ? 1 : 0);

if (successfulCount == buildResults.Length)
{
reporter.Output("Hot reload of scoped css succeeded.", emoji: "🔥");
}
else if (successfulCount > 0)
{
reporter.Output($"Hot reload of scoped css partially succeeded: {successfulCount} project(s) out of {buildResults.Length} were updated.", emoji: "🔥");
}
else
{
reporter.Output("Hot reload of scoped css failed.", emoji: "🔥");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,28 @@ public static bool IsNetCoreApp(this ProjectGraphNode projectNode, Version minVe

public static IEnumerable<string> GetCapabilities(this ProjectGraphNode projectNode)
=> projectNode.ProjectInstance.GetItems("ProjectCapability").Select(item => item.EvaluatedInclude);

public static IEnumerable<ProjectGraphNode> GetTransitivelyReferencingProjects(this IEnumerable<ProjectGraphNode> projects)
{
var visited = new HashSet<ProjectGraphNode>();
var queue = new Queue<ProjectGraphNode>();
foreach (var project in projects)
{
queue.Enqueue(project);
}

while (queue.Count > 0)
{
var project = queue.Dequeue();
if (visited.Add(project))
{
foreach (var referencingProject in project.ReferencingProjects)
{
queue.Enqueue(referencingProject);
}
}
}

return visited;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<base href="/"/>

<link rel="stylesheet" href="@Assets["lib/bootstrap/dist/css/bootstrap.min.css"]"/>
<link rel="stylesheet" href="@Assets["app.css"]"/>
<link rel="stylesheet" href="@Assets["RazorApp.styles.css"]"/>
<ImportMap/>

@*
<link rel="stylesheet" href="lib/bootstrap/dist/css/bootstrap.min.css"/>
<link rel="stylesheet" href="app.css"/>
<link rel="stylesheet" href="RazorApp.styles.css"/>
*@

<link rel="icon" type="image/png" href="favicon.png"/>
<HeadOutlet @rendermode="InteractiveServer"/>
</head>

<body>
<Routes @rendermode="InteractiveServer"/>
<script src="_framework/blazor.web.js"></script>
</body>

</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
@inherits LayoutComponentBase

<div class="page">
<div class="sidebar">
<NavMenu/>
</div>

<main>
<div class="top-row px-4">
<a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a>
</div>

<article class="content px-4">
@Body
</article>
</main>
</div>

<div id="blazor-error-ui" data-nosnippet>
An unhandled error has occurred.
<a href="." class="reload">Reload</a>
<span class="dismiss">🗙</span>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
.page {
position: relative;
display: flex;
flex-direction: column;
}

main {
flex: 1;
}

.sidebar {
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
}

.top-row {
background-color: #f7f7f7;
border-bottom: 1px solid #d6d5d5;
justify-content: flex-end;
height: 3.5rem;
display: flex;
align-items: center;
}

.top-row ::deep a, .top-row ::deep .btn-link {
white-space: nowrap;
margin-left: 1.5rem;
text-decoration: none;
}

.top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
text-decoration: underline;
}

.top-row ::deep a:first-child {
overflow: hidden;
text-overflow: ellipsis;
}

@media (max-width: 640.98px) {
.top-row {
justify-content: space-between;
}

.top-row ::deep a, .top-row ::deep .btn-link {
margin-left: 0;
}
}

@media (min-width: 641px) {
.page {
flex-direction: row;
}

.sidebar {
width: 250px;
height: 100vh;
position: sticky;
top: 0;
}

.top-row {
position: sticky;
top: 0;
z-index: 1;
}

.top-row.auth ::deep a:first-child {
flex: 1;
text-align: right;
width: 0;
}

.top-row, article {
padding-left: 2rem !important;
padding-right: 1.5rem !important;
}
}

#blazor-error-ui {
color-scheme: light only;
background: lightyellow;
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
box-sizing: border-box;
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
}

#blazor-error-ui .dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<div class="top-row ps-3 navbar navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="">RazorApp</a>
</div>
</div>

<input type="checkbox" title="Navigation menu" class="navbar-toggler"/>

<div class="nav-scrollable" onclick="document.querySelector('.navbar-toggler').click()">
<nav class="nav flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Home
</NavLink>
</div>
</nav>
</div>
Loading

0 comments on commit 6224ed9

Please sign in to comment.