dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
34.59k stars 9.79k forks source link

Hot Reload for Blazor #5456

Closed danroth27 closed 2 years ago

danroth27 commented 6 years ago
SteveSandersonMS commented 6 years ago

See https://github.com/aspnet/blazor/issues/193 for status updates on this work item.

martasp commented 6 years ago

For now, we can use dotnet watch run and recompile every time when the change occurs. Just using this in csproj file : <DotNetCliToolReference Include="Microsoft.DotNet.Watcher.Tools" Version="2.0.0" /> <Watch Include="**\*.cshtml"/>

danroth27 commented 6 years ago

We've hit a snag with live reload for 0.2.0, so moving this out until we can work through a more robust design.

ghost commented 5 years ago

Hi, I'm using dotnet sdk 2.2.100-preview1-009349 and blazor 0.5.1 under Mac. Live reload doesn't work using "dotnet blazor serve". If I change some html markup in a cshtml file, the app doesn't reload itself and ever after a manual browser reload, the app display the old html content. How can I solve this?

mkArtakMSFT commented 5 years ago

@danroth27, what's https://github.com/aspnet/AspNetCore/issues/4056 then? Should it be closed?

dazinator commented 5 years ago

Few questions! 1 Does this track live reload for both server side blazor and client side blazor?

  1. Will live reload ship in go live release (i.e in net core 3.0) ?
  2. Will live reload mechanism lose page state (I.e equivalent to an f5 refresh) or will it behave similar to Hot Module Replacement in javascript land - I.e only the changed Components UI will re-render? If the latter, will there be a mechanism to preserve component state on the client between updates?
danroth27 commented 5 years ago

Does this track live reload for both server side blazor and client side blazor?

Yes

Will live reload ship in go live release (i.e in net core 3.0) ?

For .NET Core 3.0 we expect to support auto rebuild based on file changes, but you will still need to manually refresh the browser.

Will live reload mechanism lose page state (I.e equivalent to an f5 refresh) or will it behave similar to Hot Module Replacement in javascript land - I.e only the changed Components UI will re-render? If the latter, will there be a mechanism to preserve component state on the client between updates?

We don't currently have a plan for supporting hot module replacement in a way that preserves client state.

SteveSandersonMS commented 5 years ago

We don't currently have a plan for supporting hot module replacement in a way that preserves client state.

At least, not automagically. Theoretically if you follow a Redux-like architecture, or anything else that strictly decouples state from display, then you could serialize that state out before unload and restore on reload. However this isn't something we're planning to bake in as a feature, as not everyone wants to follow that kind of architecture.

dazinator commented 5 years ago

then you could serialize that state out before unload and restore on reload.

Thanks. Please, once ready, would you be able to document the appropriate hooks (before unload / reload etc) provided in the design to facilitate this. I'd like to start on an implementation / helper nuget package to enable this pattern for those that want it!

ahmad2smile commented 5 years ago

Couldn't get the dotnet watch run to work, tried following and other options too,

dotnet watch --project "Portfolio.Client" run --project "Portfolio.Server"

Just ended up with the following crude solution using nodemon:

npx nodemon --watch "Portfolio.Client" -e razor,css,html,cs --exec 'dotnet run --project "Portfolio.Server"'

yberstad commented 5 years ago

I thought i was supposed to run: dotnet watch --project BlazorTest.Client run But that gave me an error.

If I used: dotnet watch --project BlazorTest.Server run

With the following in the project BlazorTest.Server.csproj file:

<ItemGroup>
    <Watch Include="..\**\*.razor" />
    <Watch Include="..\**\*.scss" />
    <Watch Include="..\**\*.cs" />
</ItemGroup>

It picked up changes in the BlazorTest.Client project and restarted the server, so I only had to do a manual refresh in the browser.

dazinator commented 5 years ago

It picked up changes in the BlazorTest.Client project and restarted the server, so I only had to do a manual refresh in the browser.

Does that mean the server restarts everytime there is a a css, html change?

yberstad commented 5 years ago

@dazinator, yes :-)

dazinator commented 5 years ago

.. ok just checking but that is a bad thing right? I.e server restart should be unnecessary for a html or css file change as a browser refresh (with cache invalidated) should suffice?

yberstad commented 5 years ago

You are right, that is not necessary. Just add or remove the file extensions you are interested in within the <ItemGroup>. Updated my answer to avoid confusion.

datvm commented 4 years ago

Sorry if off-topic, is there anyway to live reload from Visual Studio right now (Blazor client-side)? Right now for every change excluding wwwroot files, I have to Build the project (Ctrl Shift B) and reload the browser. Would be wonderful if VS can auto build on saving changes.

danroth27 commented 4 years ago

@datvm We've enabled this for server-side Blazor projects, but we need to do some work to enable this again for client-side Blazor projects and Razor class libraries. It will probably be a bit before we get to this as we are focused right now at shipping .NET Core 3.0.

dazinator commented 4 years ago

For client side, you can probably use anything that just does a full page refresh when something changes on the server. Shameless plug: check out NetPack - run the sample project and navigate to the /BrowserReload example: https://github.com/dazinator/NetPack/blob/develop/src/NetPack.Web/Views/Home/BrowserReload.cshtml - that might help you. If not, there are other solutions out there for triggering a client side page reload based on server side file changes if you can't wait for an out of the box solution.

datvm commented 4 years ago

Thanks for the solution, may actually be useful for someone else. For me it will just be a QoL improvement, nothing critical. Still love the product and the effort everyone is putting in. Extra pressing of Ctrl Shift B works for me (now).

AdmiralSnyder commented 4 years ago

My solution currently looks like this: I have a separate exe BlazorDebugLauncher which gets started by launchsettings.json parameterized with the port and hostname that the browser shall be opened. It then

If anyone is interested, I can put this somewhere...

dazinator commented 4 years ago

@AdmiralSnyder sure I'd be interested to see that if you feel like sharing!

Hubert-Rybak commented 4 years ago

Worth checking out: https://github.com/RickStrahl/Westwind.AspnetCore.LiveReload

AdmiralSnyder commented 4 years ago

this is my solution. a little hacky, but works: https://github.com/AdmiralSnyder/BlazorAutoRebuildDemo (I'll cleanup and add a readme next week…)

AdmiralSnyder commented 4 years ago

@dazinator did you happen to have a look?

dazinator commented 4 years ago

@AdmiralSnyder I had a look and thanks for sharing, I was keen to see how / whether you were attaching the debugger - I've got a bit of a vs extension development background you see :-) i've settled on this approach for browser reload though (it's my own library unsurprisingly) https://github.com/dazinator/NetPack/blob/develop/src/NetPack.Web.Blazor.Host/Startup.cs - which runs the watcher within the app itself (using IFileProvider) rather than launching any external processes, and it triggers a reload using signal r and a blazor client side component that you add to your blazor layout. It has been working well for me in preview6 and I'll soon upgrade to preview7 and hope it continues to work :-)

AdmiralSnyder commented 4 years ago

I didn't want to bring the refreshing features into the project. How do you gap the detach-rebuild-restart-reattach gap without having an external process?

dazinator commented 4 years ago

I didn't want to bring the refreshing features into the project

You dont have to bring them into the project in a strict sense. For example you can include the package references with a condition on a compilation symbol (I.e debug = true) and you can put the startup code in a compilation directive (#if debug) - and now when you run the app in release mode you wont have the design time packages or code in it.

How do you gap the detach-rebuild-restart-reattach gap without having an external process?

Because I run the host project from VS, it can rebuild the referenced blazor client project as needed (netpack watches the blazor projects IFileProvider) without having to stop or detach from the host process. The only time there is a "gap" is if I need to make a code change to my host application itself (not the blazor client). In that case - I sorely hope one day "Edit and Continue" will work again as that will solve this last problem. However without that, there are two options for my aproach:

  1. Don't use VS to run the host, use dotnet run watch and then attach the debugger manually (a pain)
  2. Stop VS, make the change to the host, start Vs again (this is typically what I do) @AdmiralSnyder have edited this to hopefully better address your questions
srowan commented 4 years ago

I am seeing ~10 seconds for a rebuild using dotnet watch. Are there any plans to speed up incremental builds? That is fairly painful when iterating on components.

It looks like much of the time is spent building the razor components, so does that mean these build times are going to scale ~linearly? (with more complex apps taking 30+ seconds to build?)

chucker commented 4 years ago

Are there any plans to speed up incremental builds? That is fairly painful when iterating on components.

If this is client-side Blazor, consider disabling linking for Debug builds.

  <PropertyGroup Condition="'$(Configuration)' == 'Debug'">
    <BlazorLinkOnBuild>false</BlazorLinkOnBuild>
  </PropertyGroup>
Postlagerkarte commented 4 years ago

I have talked to a few people who are confused about auto-rebuild and auto-refresh. This mainly is due to the fact that when you change code in Visual Studio the auto-rebuild feature kicks in and you also see that "something" is hapening in the browser. This something is often mistaken for a live reload attempt. Then (due to the fact that the signal-r connection can not reconnect to the old state) you get the "Failed to reconnect to the server." error. However for people new to Blazor it looks like the system has tried an auto-refresh it fails in doing so which is bad experience.

Since there is no ETA on the Live Reload feature is it possible to not try an auto-reconnect if the connection broke due to a build? Or at least give a better error message, so instead of "Failed to reconnect to the server" something like "Refresh Browser"?

dazinator commented 4 years ago

@chucker thanks for the disable linker tip. That does up the build marginally but then the subsequent browser reload is much slower as it now downloads much more chaff- I'm not sure whether overall it has helped or not :-) but worth knowing. If anyone is curious to see blazor reload in action (for blazor client / wasm) projects, you can run this project here to see what I mean: https://github.com/dazinator/NetPack/blob/develop/src/NetPack.Web.Blazor.Host/Startup.cs

danroth27 commented 4 years ago

@Postlagerkarte We do try to reconnect, but since the server state is gone when the process is recycled the reconnection fails. We've done some work in this space to try to improve the user experience. See the "Improved reconnection logic for Blazor Server apps" section in the Preview 8 announcement blog post.

dazinator commented 4 years ago

@Postlagerkarte improved that error message in preview8

srowan commented 4 years ago

Depending on the horizon / timeline for live reload, Is it worth considering a separate issue to improve compile speed? Perhaps via a caching strategy similar to how MVC/cshtml works (I believe only views that have changed get recompiled)? Are there any potential low hanging fruit here?

Right now the 10 second cycle time between making a change and seeing it in the browser is just a really big issue, and is significantly larger than webpack based platforms at similar application scale. And to be clear, I'm just talking about server side blazor here.

danroth27 commented 4 years ago

Is it worth considering a separate issue to improve compile speed?

Yes, if you are seeing slow build times please file an issue with details of your build environment.

dazinator commented 4 years ago

Having to reload the entire blazor client application (re-download all dll's) when you make a minor "html only" change to a component (for example, change some static html content) is... not very optimal.

Do the team have anything to track improvements to that experience or should I open a new issue?

danroth27 commented 4 years ago

@dazinator It's not very clear from the issue title, but we are using this issue to track hot module replacement as well as live reload. We have a bunch of investments that we plan to make in the .NET 5 time frame in this area.

Postlagerkarte commented 4 years ago

Personally I don't mind hitting F5 and thus do not consider hot reloading a top prio feature, However to get into the flow I find it crucial that the change code , f5 , change code , f5 , change code workflow is blazing (pun intented) fast. Please work on that first :)

MisinformedDNA commented 4 years ago

We've enabled this for server-side Blazor projects, but we need to do some work to enable this again for client-side Blazor projects and Razor class libraries. It will probably be a bit before we get to this as we are focused right now at shipping .NET Core 3.0.

From what I've been able to gather from various GitHub issues is that live-reload only works on server-side Blazor that is run without debugging (and the developer must force refresh the page). Is that correct? I couldn't find any definitive documentation on the subject.

danroth27 commented 4 years ago

What we have right now is really auto-rebuild support for ASP.NET Core projects, where VS will watch the file system for changes and then automatically rebuild and rerun the project. It only works when the debugger is not attached and for files in the current project (dependent projects are not watched).

Postlagerkarte commented 4 years ago

Is it possible to disable the auto-reconnect attempt in case the reason for the connection loss was a build? Or maybe disable the auto-reconnect at all while developing? I just want to get rid of the those failing re-connect attempts because they bug me and I press F5 anyways :)

AdmiralSnyder commented 4 years ago

So it should be rather easy to have VS detach and reattach automatically, right?

bansalankit2601 commented 4 years ago

Can I get the final solution for Live Reloading for Blazor Server Apps with debugging ?

0xF6 commented 4 years ago

@bansalankit2601 To be implemented in .NET 5.0

dbulic commented 4 years ago

I run the watcher as dotnet watch run and use VS to edit the code. When I save, the code is recompiled and the browser locks up, telling me I should reload.

I got tired of pressing F5 and prefer to stay in VS while adjusting things, so TamperMonkey to the rescue:

// @name         Reload the page
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        http://localhost:5000/*
// @grant        none
// ==/UserScript==

    const reloader = () => {
        if (document.body.innerText.indexOf("Reload the page") >= 0) document.location = document.location;
        else setTimeout(reloader, 300);
    }
    console.log('Blazor reloader installed');
    setTimeout(reloader, 300);

Allow the script to run on http://localhost:5000/*

dharmaturtle commented 4 years ago

This works for server side: https://github.com/martasp/BlazorLiveReload

The client pings the server every 200ms. When the server goes down due to being recompiled from dotnet watch run, a flag is toggled, and when the server comes back it automatically F5s.

The repo didn't work for me, but I opened an issue with some javascript that does work (at least for me on 3.0)

moemar commented 4 years ago

What is the status of "Live reload" at the moment. Is it supported (without F5 in browser)? If not, are there any plans on releasing this feature?

nfplee commented 4 years ago

@moemar in the latest community standup David Fowler says there are plans for it for possibly the next version but nothing has been put in place yet. https://youtu.be/bBc_NTUVtbE?list=PL1rZQsJPBU2St9-Mz1Kaa7rofciyrwWVx&t=5010

aszalacinski commented 4 years ago

What is the latest on this? 2.5 months since last update...

bansalankit2601 commented 4 years ago

I am also waiting for the same.