Allow import of Blazor and DotNet JS objects from Blazor WASM startup script #48974
Labels
area-blazor
Includes: Blazor, Razor Components
design-proposal
This issue represents a design proposal for a different issue, linked in the description
enhancement
This issue represents an ask for new feature or an enhancement to an existing one
✔️ Resolution: Duplicate
Resolved as a duplicate of another issue
Pillar: Technical Debt
Status: Resolved
Milestone
Summary
As part of trying out ideas to enable multiple Blazor WebAssembly apps to co-exist on the same page (a la micro frontends as described in #38128), one thing that would be helpful is getting access to the
Blazor
andDotNet
JavaScript objects setup as part the Blazor WASM startup script (blazor.webassembly.js) through a means other than the globalwindow
object. Ideally these objects should be retrievable when the Blazor WASM startup script is loaded dynamically, such as when lazy loading a Blazor WASM application in cases like (but not limited to) Blazor-based micro frontends.Motivation and goals
As I mentioned in my comments here and here, my main motivation for supporting Blazor-based MFEs is to enable teams I work with who are more comfortable with Blazor to continue developing Blazor-based frontend modules that plug into an app shell at runtime in the browser to form one cohesive app portal experience. At the same time, I want to enable teams to build modules using JS-based technologies in those situations where it's more beneficial, such as when the module needs to interop heavily with JS-based components (e.g., Mapbox for maps, Highcharts for time series strip charts, Tableau for dashboards, and Cesium for geo-spatial visualization).
While I understand #38128 has been pushed out of the .NET 8 timeline, I wanted to continue investigating on my end things my teams can do in the short term to make Blazor-based MFEs more feasible. As a proof of concept, I made a set of patches to the Blazor WASM startup script (available on GitHub here), and I've been able to get some basic Blazor-based MFEs working (with a demo app published on GitHub here).
One constraint I see with my current approach is that I need to ensure that I only load one Blazor WASM app at a time, and by "load" I mean import the app's Blazor WASM startup script. The reason is I need to grab a reference to the
Blazor
andDotNet
objects that correspond to a particular MFE so that I can properly manage its lifecycle when I mount and unmount that MFE. I believe the one-at-a-time limitation exists due to a possible race condition I call out in my demo app here, but the basic idea is that if I try to load more than one startup script at the same time, I could possibly end up in a situation where one MFE's script will overwritewindow.Blazor
andwindow.DotNet
with its runtime objects before my code has had a chance to capture the corresponding references for the other MFE.If there were a way to get these references other than through the global namespace, my belief is that this potential race condition can get mitigated.
In scope
Given a URL to a Blazor-based MFE's startup script, I would ideally like to dynamically load it from JavaScript like so and, in the process, get the
Blazor
andDotNet
objects created when the startup script is executed by the browser:I think the ideal way of exposing this would be if the Blazor startup script were a true JS module that exported the
Blazor
andDotNet
objects. This would allow JS code to resolve those via a dynamic import using theimport()
syntax.Out of scope
I'm really only considering Blazor WASM apps at this point. Other uses of Blazor really aren't in scope with this request (and I'm not sure how relevant they would be here).
Risks / unknowns
One possible challenge of switching the startup script to a JS module is that
<script>
tags would need to specify thetype="module"
attribute to ensure the script is executed as a JS module. This would likely be a breaking change for existing Blazor WASM apps.Just as a straw man, a couple mitigations may include:
Blazor
andDotNet
objects included.Examples
See the snippet above to get a basic idea of how I would roughly expect this import mechanism to work. For a more complete context of where I would ideally like to use this capability, the bootstrap function in my demo app offers a decent example here. In that example, I'm reading the
Blazor
andDotNet
objects from thewindow
object, but getting them from the module object resolved from the dynamic import of the Blazor startup script would be the ideal outcome.The text was updated successfully, but these errors were encountered: