Bolero icon indicating copy to clipboard operation
Bolero copied to clipboard

Server remoting using XHR instead of Websockets

Open srid opened this issue 3 years ago • 6 comments

Correct me if I'm wrong, but I was under the impression that Bolero's server used websockets for real-time server remoting. But when I ran the dev server using dotnet run -p ./src/Baseline.Server on the template app (specifically https://github.com/srid/Baseline), and checked the Chrome inspector, the getBooks call is making a new HTTP request, instead using any websocket connection (there is none).

image

How should I expect it to behave? Are there documentation on this? Can we make the Bolero app using Websocket? What's the relation to SignalR if any? (I'm new to .NET).

srid avatar Mar 19 '21 17:03 srid

You have Bolero running in WebAssembly mode, so in this case, remoting indeed uses HTTP requests.

When you run Bolero in server mode (using .AddBoleroHost(server = true)), the "remote" functions are called directly, and so the only network traffic is Blazor's websocket.

Tarmil avatar Mar 20 '21 17:03 Tarmil

Thanks. Is there any reason why server = false by default? (What does this flag mean anyway? Is there an API documentation?).

srid avatar Mar 23 '21 04:03 srid

Looking at https://github.com/fsbolero/Bolero/blob/2901c7e8ee03c27fff47522af55c7735d1aba6c9/src/Bolero.Server/RazorHost.fs#L62-L67

By default, the bolero app template is in RenderMode.Static mode, and setting server=true puts it in RenderMode.Server (the prerendered variation, actually) mode. What's the difference?

From https://devblogs.microsoft.com/aspnet/asp-net-core-and-blazor-updates-in-net-core-3-0-preview-9/#render-multiple-blazor-components-from-mvc-views-or-pages

Static: Statically render the component with the specified parameters. Server: Render a marker where the component should be rendered interactively by the Blazor Server app.

A couple of questions:

  • Why is the default Bolero project template configuring the app to run in static rendering mode? As the project template generates both server and client projects, this makes little sense?
  • Why would a statically generated Wasm app not be able to use websockets?

I'm completely new to the dotnet ecosystems, so please excuse my basic questions. :-)

srid avatar Mar 23 '21 04:03 srid

Ah, my first question is out of misunderstanding I guess. The render mode is in the context of the server serving a path request, where it makes the decision to just dump the HTML (statically) or have the client build it, or prerender it and hydrate it on client. https://stackoverflow.com/a/58231378/55246

Still not sure why a statically generated response won't be able to use websockets in the client; Oh maybe something to do with SignalR?

In any case, I'd rather have prerendering enabled anyway, and don't need the performance of full static rendering. So server=true works for me.

srid avatar Mar 23 '21 04:03 srid

Aha,

https://dotnet.microsoft.com/apps/aspnet/web-apps/blazor

I guess I understood the model incorrectly.

Run on WebAssembly or the server

Blazor can run your client-side C# code directly in the browser, using WebAssembly. Because it's real .NET running on WebAssembly, you can re-use code and libraries from server-side parts of your application.

For Bolero project template, this is the default mode? So, all the code in the Client project runs in the browser, as one would expect. Of course, one can't do things like talk to the database (since database lives on the backend).

Alternatively, Blazor can run your client logic on the server. Client UI events are sent back to the server using SignalR - a real-time messaging framework. Once execution completes, the required UI changes are sent to the client and merged into the DOM.

This mode is enabled by server=true? So here, all of the logic in the Client project actually runs on the server, but Bolero injects some sort of JavaScript stub (not Wasm!) that will send UI events to the backend, which in turn sends any UI updates down to the frontend, all via SignalR - hence websocket is used.

Is my understanding correct, @Tarmil ?

Which mode is suitable for production? Are there any factors I should consider when choosing between the two? What are the downsides (in production with lightweight traffic) of going with the server=true mode?

srid avatar Mar 23 '21 04:03 srid

You can run SignalR on the client in WebAssembly mode (blazor docs). My app is hosted with ASP.NET but it might work with other hosting models as well. I ended up dropping the remote services and replacing server-client communication with a SignalR connection hooked into Elmish subscriptions to trigger updates as recommended in this issue. It would be cool if you could setup remoting with a SignalR connection like this out of the box but I haven't looked into the remoting implementation and it might not be trivial to provide that option.

One disadvantage of the Blazor Server (server=true) approach is that any UI event needs to go over the network along with the resulting html diff. In WebAssembly mode you can do a lot of logic on the client and only send what you need to the server, such as persistence data. There are other considerations nicely outlined here.

sdehm avatar Sep 13 '21 20:09 sdehm