dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.84k stars 4.62k forks source link

Blazor webassembly startup speed and UI locking issue #65559

Open mattgenious opened 2 years ago

mattgenious commented 2 years ago

Description

When starting up mono and blazor the UI, e.g. input fields, are locked until the webassembly has finished processing.

This is not related to network speed and cannot be fixed by lazy loading as the mono runtime and subsequent blazor application still locks the UI while loading.

This is a larger issue because when prerendering first and then triggering the startup process the user experience is an instantly loaded page, that then hangs and locks all UI until page load is finished. In the case where you succeeded in entering data before the UI locking startet, this too is deleted unless a mechanism to transfer input data from the prerendered site to the live app is implemented using javascript.

Reproduce:

  1. Create a blazor webassembly app on .NET 6.0 LTS, with no authentication, configured for https and hosted on ASP.NET Core but without progressive web application features enabled.
  2. In index.html add <input type="text" class="form-control" /> below <div id="app">Loading...</div>
  3. In Index.razor add the following to see in console log when first render is processed to indicate the app has finished starting.
  4. Publish the app in release mode to folder and run the generated exe file.
  5. Navigate to https://localhost:5001
  6. Check that the input field present while loading is locked, this is before the app displays on the white page with the "Loading..." text in the top right corner.

Configuration

Microsoft Windows 11 Pro 10.0.22000 Build 22000 AMD Ryzen 9 3900X 12-Core Processor, 3793 Mhz, 12 Core(s), 24 Logical Processor(s) 32.0 GB RAM Firefox and Chrome browsers

&

iOS 12.2 iPhone 5s Safari 12

&

iOS 15.4 iPhone 12 Pro Safari 15

Data

Windows 11 PC: Firefox console output:

Screenshot 2022-02-18 104427

Chrome lighthouse and performance profile results: blazor performance chrome lighthouse and performance profile.zip

Firefox performance profile results: Firefox 2022-02-18 10.41 profile.json.gz

iPhone 12 Pro: https://user-images.githubusercontent.com/3007300/154679804-f67aa2d9-5c69-4f6e-9165-f5ed0681db5e.mp4

iPhone 5s: https://user-images.githubusercontent.com/3007300/154679884-3bad3145-0e85-4a98-96ce-b890380f0b8c.MP4 https://user-images.githubusercontent.com/3007300/154679892-bb7bcd5f-7f78-4630-a334-867b216455bf.MP4

Analysis

As far as I understand part of the issue is that the mono runtime and systems that build on top are locked to using a single thread for everything including the UI, this causes the UI to freeze during initialization of the runtime and application.

If this was solved however a new problem would be users interacting with the prerendered site and then losing what they already filled out in input fields and so on as soon as the app loads unless the developers implemented a function to handle this case on a per site/input field basis which does not seem like a scalable or elegant solution.

I suggest mono and blazor allow for use of multithreading in wasm to allow interaction during load and suggest an automatic mechanism for transferring input in prerendered fields to live fields once the app is loaded.

For reference to other issues tracking a similar topic i refer to: https://github.com/dotnet/aspnetcore/issues/17730 https://github.com/mono/mono/issues/12453 https://github.com/WebAssembly/threads/issues/163

dotnet-issue-labeler[bot] commented 2 years ago

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

ghost commented 2 years ago

Tagging subscribers to 'arch-wasm': @lewing See info in area-owners.md if you want to be subscribed.

Issue Details
### Description When starting up mono and blazor the UI, e.g. input fields, are locked until the webassembly has finished processing. This is not related to network speed and cannot be fixed by lazy loading as the mono runtime and subsequent blazor application still locks the UI while loading. This is a larger issue because when prerendering first and then triggering the startup process the user experience is an instantly loaded page, that then hangs and locks all UI until page load is finished. In the case where you succeeded in entering data before the UI locking startet, this too is deleted unless a mechanism to transfer input data from the prerendered site to the live app is implemented using javascript. Reproduce: 1. Create a blazor webassembly app on .NET 6.0 LTS, with no authentication, configured for https and hosted on ASP.NET Core but without progressive web application features enabled. 2. In index.html add `` below `
Loading...
` 3. In Index.razor add the following to see in console log when first render is processed to indicate the app has finished starting. 4. Publish the app in release mode to folder and run the generated exe file. 5. Navigate to https://localhost:5001 6. Check that the input field present while loading is locked, this is before the app displays on the white page with the "Loading..." text in the top right corner. ### Configuration Microsoft Windows 11 Pro 10.0.22000 Build 22000 AMD Ryzen 9 3900X 12-Core Processor, 3793 Mhz, 12 Core(s), 24 Logical Processor(s) 32.0 GB RAM Firefox and Chrome browsers & iOS 12.2 iPhone 5s Safari 12 & iOS 15.4 iPhone 12 Pro Safari 15 ### Data Windows 11 PC: Firefox console output: Screenshot 2022-02-18 104427 Chrome lighthouse and performance profile results: [blazor performance chrome lighthouse and performance profile.zip](https://github.com/dotnet/runtime/files/8096964/blazor.performance.chrome.lighthouse.and.performance.profile.zip) Firefox performance profile results: [Firefox 2022-02-18 10.41 profile.json.gz](https://github.com/dotnet/runtime/files/8096951/Firefox.2022-02-18.10.41.profile.json.gz) iPhone 12 Pro: https://user-images.githubusercontent.com/3007300/154679804-f67aa2d9-5c69-4f6e-9165-f5ed0681db5e.mp4 iPhone 5s: https://user-images.githubusercontent.com/3007300/154679884-3bad3145-0e85-4a98-96ce-b890380f0b8c.MP4 https://user-images.githubusercontent.com/3007300/154679892-bb7bcd5f-7f78-4630-a334-867b216455bf.MP4 ### Analysis As far as I understand part of the issue is that the mono runtime and systems that build on top are locked to using a single thread for everything including the UI, this causes the UI to freeze during initialization of the runtime and application. If this was solved however a new problem would be users interacting with the prerendered site and then losing what they already filled out in input fields and so on as soon as the app loads unless the developers implemented a function to handle this case on a per site/input field basis which does not seem like a scalable or elegant solution. I suggest mono and blazor allow for use of multithreading in wasm to allow interaction during load and suggest an automatic mechanism for transferring input in prerendered fields to live fields once the app is loaded. For reference to other issues tracking a similar topic i refer to: https://github.com/dotnet/aspnetcore/issues/17730 https://github.com/mono/mono/issues/12453 https://github.com/WebAssembly/threads/issues/163
Author: mattgenious
Assignees: -
Labels: `arch-wasm`, `tenet-performance`, `area-VM-meta-mono`
Milestone: 8.0.0
maraf commented 1 year ago

In combination with prerendering, it would help to run main .NET thread on web worker and attach Blazor state with prerendered UI.

pavelsavara commented 9 months ago

Possibly this solved by "Interactive Auto" rendering mode in .Net 8?

I'm working on threading design here https://github.com/dotnet/designs/pull/301

And I'm thinking what would be impact of threading on Blazor's background loading of WASM.

cc @javiercn @danroth27