-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Avoid completely replacing the DOM when Blazor components are re-rendered after prerendering #42561
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Thanks for contacting us. We're moving this issue to the |
Yes yes yes. This is long overdue my guys 🙏😍😇 |
Great to see this is finally being worked on. Let's hope it doesn't get pushed off any longer. |
You can refer ilovedotnet for this issue. The site is built from scratch using blazor wasm and the site also facing flicker issue when it gets loaded. The site has prerendering enabled during publish time in the pipeline. When the site loads the prerendered screen appears and when the blazor engine kicks in, there comes a flash and screen appears after that. |
Thanks for contacting us. We're moving this issue to the |
Agreed. Without making this transition seamless, SSR is pretty useless right now. This is a must-have to compete with the competitors in the market. |
And now I've simply replaced the WebAssembly interactivity with HTMX. What a cobbled mess Blazor has become. |
This has been such a huge issue to so long, it kinds of blows my mind that the ASP.Net team keeps pushing it out as if it weren't important. I agree with other commenters, after doing several Blazor sites in .Net 6, Blazor has become a cobbled mess. I switched to Blazor Server to get around WASM load speed issues, but now I wish I'd pulled the trigger on HTMX several months ago. |
@javiercn I'm curious to know the plans to work on this issue. It's been there for a very long time from since I started using blazor WASM from the initial release. What's the thoughts of ASP.NET team on this? |
@andersme you mean you switched to plain HTML? Can you explain more? I'm also looking for alternatives now. |
HTMX is another competitor and is similar to Knockout.js and Angular 1. If someone wants to build websites like it's 2010, go for it 😄 |
Without this feature, preventing the flicker (or reducing its effects) requires a lot of work and creativity on both the server and the client side. Since other competitors have this (smooth hydration) out of the box, it has a big impact on projects developed by Blazor. We love Blazor and the vast opportunities it opens for .NET developers, and I hope this won't be delayed any further than the .NET 10 milestone 🤞. |
basically, similar to https://alpinejs.dev/ it is fine when you need just very little interactivity and basically use Blazor as static rendering = fast loading time, no flickering etc.. but it is definitely not good tradeoff for anything other than very simple website (in terms of interactivity / front-end logic). |
Bummed to see the recent comments and current state on this issue. We also removed Blazor based interactivity from our app and mvoed to one of the HTMX variants (Datastar). |
I've not found this to be much of an issue myself. I'd rather not hold up the server side pre-render with async database type work, just to do it again when the page goes interactive. I'd rather that initial render was as fast as possible with loading indicators in place of interactive content, which is pretty straightforward. Either, move your async code from OnInitializedAsync to OnAfterRenderAsync inside the first render if block, or wrap it in 'if (RendererInfo.IsInteractive). Voila, your page pre-renders fast, you do your async work once, and the dynamic async content appears when it's interactive (no flicker) which is pretty quick when published. There's often not a great deal of value rendering that content before that point anyway as it tends to be in components that need interactivity anyway. (I think it can be worse to get pixels onto the screen, to then have clicks ignored because something isn't interactive yet). If you're determined to have this stuff in the oninit/pre-render, have a look at the community stand up 'what's new for Blazor in .Net 10' on YouTube. About 40 mins in, you can see what you can do to persist state today, and what's coming. That's all overhead though, I think you'd need a pretty good reason to want to for pre-rendering. Makes a bit more sense for Blazor server and persisting state on reconnect. |
@mip1983 It's not that simple. For example, consider the SEO of dynamic data, which is a big requirement. There are other important requirements that need the prerender to work, as explained in this issue. |
Like I said:
|
Like I said, it's not that simple. |
Being able to pre-render drastically improves any SEO performance as it will send a skeleton of the HTML with all of your SEO friendly wording in it to the search engine. |
What's an example of something you can't work around at the moment? Can you not pre-render and hydrate your SEO related content this way? https://www.youtube.com/live/IXU3hbnaX50?t=2218s |
As I've said, it's not that simple, so I hope I can explain it clearly. The problem, as explained in the issue itself, is something that happens at the lower levels of the Blazor rendering while hydrating the app after initialization for the first time when receiving the pre-rendered content. |
What problems are your users experiencing? Do you have a video you can share? |
When a prerendered document is retrieved by the browser, CSS files begin downloading. While these user interface interactions are occurring, JavaScript files start downloading in the background, followed by hundreds of (WASM) files. After that, a prerendered state (encoded as a base64 JSON string located at the bottom of the document's body) is read and deserialized into the corresponding classes (The ASP.NET Core team has ensured that no System.Text source generators can be used in this process, deliberately 😅 keeping it slow) The process of downloading and executing code may take several seconds, depending on the client's network conditions, the size of the web app, and the processing power of the client's device CPU. When this finishes, the list of items the user had scrolled through resets to the top, any video restarts from the beginning, animations replay, and the CSS-based carousel returns to the first photo. This moment is marked as the Largest Contentful Paint (LCP), even though the user could already read the content seconds earlier! Why would you need a video to explain such an obvious scenario? @3hxx |
Yeah, I don't understand the recent questions asking to justify this issue. The original issue was filed by an MS employee, the description in it is clear. All the reactions above clearly indicate it is not a solitary problem. I and others have ditched Blazor interactivity or Blazor entirely because of it. What is the skepticism here? |
I'm not saying this isn't a nice thing to get solved, but for people to say it makes Blazor interactivity unusable or that you have to jump to another framework seems a bit of an over the top reaction. I'm just trying to inject some first hand experience/realism and share some work arounds and upcoming changes that will help. I have a my own real world Blazor site infront of me. It pre-renders quickly, you get the main layout, menu, placeholder widgets and loading indicators, there's a video background splash screen on load, CSS animations into a complex interactive (wasm) dashboard with charts and carousels, all of which play once with no flicker, going from 0 to interactive in ~1s (regardless of whether I'm on my desktop or low powered mobile). If you where to read ysmoradi description, you'd think that was basically impossible or really hard to do. It isn't. |
Good for you. And your site sounds really fleshed out which is also great. I get that you're not seeing this issue but that fact by itself doesn't invalidate that others have seen this issue. I've been where you are (not seeing the issue others are seeing), and likely others have too. Never makes sense to dismiss other's experiences, scenarios, sense of urgency etc. Hydrating pre-rendered content is something nearly every FE framework does today. It's frankly embarrassing for something like this to be status quo that requires significant workarounds to implement (assuming it can be worked around). if you have helpful tips here or know of a given solution, we're all ears. Otherwise it's just a shite attitude. |
Let's talk with real examples. https://bitplatform.dev/ is the smallest website we've ever built using Blazor WebAssembly, with a total size of just 2.5MB. Another example is https://sales.bitplatform.dev/, which comes in at 3MB. On a low to mid-range Android device with a 4G connection, these ultra-light websites take around 4 seconds to become interactive. I'm guessing you're referring to a desktop setup with a powerful PC and a high-speed network. If you share your website's URL here, I can say how long it would take to become interactive on a Galaxy A35 with a 4G connection @mip1983 |
I am a cms and website developer. The biggest limitation of Blazor is on web development where it is mandatory to use prerender for obvious reasons related to seo. Making the user wait a few seconds (especially on mobile) to use the interactive buttons is unacceptable. So much so that on the sites, with the exception of pages that can be rendered without prerender, such as the cart, I had to replace the interactivity with htmx. |
Right now, after prerendering we replace the entire contents of the prerendered component with a fresh DOM copy created from scratch. This has several bad side-effects like:
Instead of replacing the contents of the DOM wholesale, we can do a best effort to reconciliate the DOM with the new rendered DOM when we are trying to apply the render batch.
In an ideal scenario, a developer should be able to produce exact prerenders, meaning that the render after prerendering is identical to the prerendered one.
In that case, the renderer would only need to "attach" event handlers to the appropriate nodes, leaving everything else the same.
The renderer does not have to be perfect and handle all possible scenarios, it can impose strict limitations and "bail out" if it can't figure out how to reconcile a given DOM subtree by replacing that node wholesale.
For example, the render can impose a strict order, suggesting that DOM children nodes in a given subtree must appear in the same order as the prerendered node (in other words, the renderer won't search for them, but iterate in order). A similar restriction might be imposed on attributes (which is not rare, since attributes are emitted in compilation order, except for splatting). Things like
@key
could be leveraged during prerendering too to offer a bit more flexibility in the ordering.In general, this will likely result in a much higher node reuse and will give the developers the chance to always get this right.
The text was updated successfully, but these errors were encountered: