Replies: 5 comments 1 reply
-
First of all, thank you for the efforts taken into improving this area, I myself have been giving you quite a few issues around it. As for the system, I believe the default approach should be different depending on the render mode. For example, in static SSR perhaps it shouldn't be opt-in and it makes more sense for it to be "Once" by default. You would only use "Always" or "PageScript" for specific cases. On the other hand, in interactive render mode it might be wiser for the default value to be "Never" as you could load it via jsinterop. I believe this might make more sense for new developers. |
Beta Was this translation helpful? Give feedback.
-
I like it! The Load property strikes a good balance between backward compatibility, explicit control, and future extensibility. Flagging the Reload property as deprecated ensures a smooth migration path while minimizing confusion for developers. The approach is well-aligned with Blazor's design principles of being developer-friendly and predictable. |
Beta Was this translation helpful? Give feedback.
-
@mdmontesinos the "Reload" property was introduced specifically for Static rendering - it was never intended to be used with Interactive rendering, as Interactive rendering uses a different approach for dealing with scripts due to the fact it is a SPA. In Oqtane, Interactive rendering uses LoadJS to dynamically load scripts and essentially follows the "Once" approach as LoadJS only reloads a script if it was not already loaded previously. The equivalent to "Always" in Interactive rendering is to call JS Interop from OnAfterRenderAsync. And there is no equivalent for "PageScript" as it is not applicable in Interactive rendering (as there is no 'enhancedload' event). I do agree that in Static rendering it does make sense that the default for Resources should be "Once" as this ensures that new scripts are always loaded. You are correct that "Always" is only applicable to scripts which need to execute on every Enhanced Navigation. Maybe it would be clearer if the new property was named "StaticLoad" rather than "Load"? |
Beta Was this translation helpful? Give feedback.
-
This scenario had never been considered when Reload was introduced. However, I can now imagine a scenario where a developer created a script in the format expected by BlazorPageScript (ie. it implemented the onUpdate() method) and registered the Resource as Reload=True. When running on Static Blazor, the framework would inject the
The difference between "Always" and "PageScript" is that PageScript loads a script as a strict JavaScript module, provides multiple events which can be hooked, and generally provides more granular control over execution... however this comes at the cost of having to follow PageScript's specific conventions and writing more custom JavaScript code. "Always" is much more simplistic and will be executed on every enhanced navigation, without any specific conventions. "Always" is much better for simple in-line scripts you want to execute. |
Beta Was this translation helpful? Give feedback.
-
#4995 introduces the changes discussed above.... New Resource class property named LoadBehavior of type ResourceLoadBehavior:
The Reload property is deprecated and will assume the LoadBehavior.BlazorPageScript approach for backward compatibility |
Beta Was this translation helpful? Give feedback.
-
In .NET 8 Microsoft introduced Static Server-Side Rendering (SSR). By default it utilizes Enhanced Navigation to simulate a SPA experience for users. Enhanced Navigation causes challenges for JavaScript integration, and currently Microsoft does not offer any "official" solution for developers who need to use JavaScript.
Mackinnon Buck from the Microsoft Blazor team created an unofficial open source project called BlazorPageScript. The primary use case for this project was to execute JavaScript after an Enhanced Navigation, by implementing some specific events (ie. onUpdate) which were part of its interface definition. However the project also contained the capability to load JavaScript modules, so some developers assumed it was also intended to be used for general JavaScript loading purposes. This was not the case - which is why support for extended attributes such as integrity and crossorigin were never included. Mackinnon Buck has since superseded BlazorPageScript with another unofficial open source project called BlazorJsComponents, which has some additional capabilities but is also not intended to be a general JavaScript loader.
Oqtane integrated BlazorPageScript in the 5.1 release as it needed to provide a way for developers to execute JavaScript after an Enhanced Navigation. A Reload property was added to the Resource class for this purpose. When Oqtane encounters a Script Resource identified as Reload=True, it injects a
<page-script>
element into the page rather than a standard<script>
element. An example theme (Arsha) was shared to demonstrate how this capability could be utilized.Later, it became clear that there are many additional challenges which developers experience when integrating JavaScript in Static Blazor. One of the main ones is related to simply declaring script elements on a per page basis - as if a script was not part of the initial page loaded for a site, it will be ignored on subsequent navigations. This results in strange behavior and broken functionality.
Recently I did a deep dive into Blazor JavaScript integration and discovered that there is a way to prevent Static Blazor from ignoring scripts. I referred to it as BlazorScriptReload and the initial implementation was included in Oqtane 6.0.1. I also created a stand-alone version of the solution which can be utilized outside of Oqtane in standard Blazor Web Applications. Broader testing led to refinement of the solution and the changes now need to be integrated back into Oqtane.
The main change is that the original implementation used an implicit (opt-out) approach where all script elements on a page were automatically processed (unless identified otherwise). This approach is risky as it can potentially affect the behavior of existing scripts. The new version uses an explicit (opt-in) approach where a script element must include a data-reload attribute for it to be processed... and in fact there are 2 distinct settings - data-reload="always" (always reload) and data-reload="once" (only reload if it has not been loaded previously).
So the dilemma now is that there are actually 3 different scenarios related to Reload which need to be supported:
<page-script>
approachThe existing Reload property on the Resource class is a boolean... so it cannot accommodate all of these scenarios. For backward compatibility it would be best if the existing Reload property continued to be used for the
<page-script>
approach. Which means that a new property is needed to control the new behavior.My suggestion to to name the property "Load" and allow values of "Never" (default), "Always", "Once", and "PageScript" (the legacy Reload property would continue to be supported but it would be flagged as deprecated in favor of using Load = PageScript).
Feedback is welcome...
Beta Was this translation helpful? Give feedback.
All reactions