Closed danroth27 closed 4 years ago
And another aspect that I believe is of interest to people with existing systems: Is there a way to support a hybrid solution, e.g. an ASP.NET MVC application with some parts implemented using Blazor?
Is this the wrong question and/or does this warrant creating a separate issue?
Perhaps I'm asking to fly to the next galaxy while you guys are trying to just get launched into space in the first place....
@ManfredLange Nothing to share on the design for lazy loading quite yet.
As for ASP.NET MVC, you can use Blazor with any backend that you'd like including non-.NET back ends like Java, JavaScript, PHP, etc, although we make it particularly easy to use Blazor with ASP.NET Core. However, Blazor today takes full ownership of the app and the DOM, so you can't really use MVC to render some HTML on the server and then use Blazor to manipulate the DOM on the client. We are however looking at server-side pre-rendering support for Blazor.
@danroth27 link above broken. here's the fixed version server-side pre-rendering, I wish GitHub let you do it the way you tried though. You have to put [24] in brackets rather than [#24]
@mungojam Thanks! Fixed
@danroth27 I am not sure, but does it means that Lazy loading will solve this kind of problem? Can it be coupled with "Mozilla HACKS" about WebAssembly?
@ckams Lazy loading is about being able to break your Blazor app up into multiple areas that can be loaded independently. It's Blazor specific, so not related to ASP.NET Core MVC and server-side rendering. You do get the perf benefits of WebAssembly in the browser.
@danroth27 I'm not sure I understand. Sorry :s Is Lazy loading like Application Parts? Can Lazy loading be used to load multiple areas in WebAssembly from server-side?
Is Lazy loading like Application Parts?
Nope
Can Lazy loading be used to load multiple areas in WebAssembly from server-side?
Yes, lazy loading allows you to load different areas of your app client-side from the server as needed. It's similar to lazy loading in frameworks like Angular or React.
I don't see target release. Any idea in which release this feature will be available?
@abhishekgoenka Sorry, but we don't know when this feature will land quite yet.
I'm imagining two levels of lazy loading: page level and component level. This will allow the Blazor team to deliver in phases, whichever is easier first (perhaps page level?).
At page level, the entire page is lazy loaded. Thus, in an app, a page's assembly is only loaded to the browser until the user clicks on the page's link. A page would have to be declared as lazy (ex. @lazy "appname.pagename.wasm"
).
At component level, the component can be declared @lazy "appname.componentname.wasm"
. In this sense, the component's assembly will be loaded only when the page that needs it is loaded.
Thus, the @lazy directive can be used by the engine to generate different wasm's that can be "plugged in" to the client at runtime upon request (via page and/or component that needs it). I'm thinking WebAssembly's dynamic linking comes to play here (if I'm understanding it correctly)? Or perhaps Blazor will provide the mechanism to allow it?
@danroth27 would it be possible to get any news regarding ETA of lazy loading?
@hokusp Unfortunately there isn't any news to share at this point. This feature is on our backlog, but we don't expect to get to it any time soon. Our current thinking is that Lazy Loading is not critical for shipping Blazor v1.0. We still want to support it though, and we expect it would ship in a follow on release.
To help us ensure that we are prioritizing this feature correctly, it would be great if folks could share with us more details on how you expect to use this feature and why it's important for your scenarios.
Just because Dan asked 👍
In my opinion, Lazy Loading is essential for Blazor to be able to provide a good support for PWAs and a faster web experience in general.
My use case for lazy loading is simply that any page containing its most usable components should be able to be presented to the user within a max of 2 seconds from first visiting the site. This means that both pages and components should be able to be identified as lazy-loaded. Along with lazy loading a page, it would be great if an already loaded page could hint on the next page/components to be loaded and like this triggering a pre-fetching or nav pre-loading mechanism. PWAs can use Service Workers to do pre-fetching but that would not play nicely with Blazor app if no APIs are provided to facilitate it through Blazor.
For my current project, it would be great if I could load Blazor components as independent modules. I have a website where different modes will be added over time and those modes should not be coupled to the "mainproject", it should be possible that different independent people develop them and that they can be added to the site without redeploying the whole site. I imagine it a bit like an API controller: There is a request to the server /GetAppMode("identifier") and it then loads the module "identifier" and returns it to the client.
As for lazy loading, lazy dlls (library projects in general) should be the easiest ones to implement. With this approach, splitting the app in multiple assemblies will simply mean that a request for the dll is made the moment it's required, not before. Then, you could use standard .NET functions like GetAssemblies, GetReferencedAssemblies, etc to know which assemblies (modules) are already loaded.
I don't know a lot about the implementation in this area, sorry if what I'm saying doesn't make sense.
This is one of the key must-have feature that is missing and keeping us away from adapting Blazor. The concept of representing Areas (https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/areas?view=aspnetcore-2.2) as lazy-load modules would be a good approach. Until this feature is added, it is hard to consider Blazor for medium to large size enterprise applications.
Please consider this as a priority feature.
@danroth27 are there any updates on this?
Thanks for this feedback, @ganu81! This feature isn't going to fit in .NET Core 3.0, but we will consider it as part of our post-3.0 planning.
I agree this is the main reason blazor wasm is so appealing. Modularity. This is the only piece lacking ( to achieve complete decouplization ). This feature should be #1 in my opinion ABOVE ALL OTHERS!!! Can't believe after 2 years this is still a forgotten feature and still unbelievably necessary
Looks like this feature is moved to 5.0 milestone. This makes it very difficult to consider this for large/enterprise applications (and in turn makes it hard to invest knowledge in knowing you are limited to using it for hobby/small projects). +1 for making this a higher priority!
It's equally important for other Blazor scenarios, not just web assembly.
Lazy Loading is definitely important for large projects, otherwise it requires either breaking the app out into multiple sites that are loosely coupled together through shared libraries or the whole application needs to be downloaded just to use it.
Is it possible to plan out the functionality in alignment with the current milestones and then handed over to the community to contribute?
To me this is blocking for the April/May release of Blazor WebAssembly edition. Until this is available (and just automatically works with routing at the very least), Blazor Webassembly can't be used for anything but POC or "hello world". You might as well not release this without this functionality. Anyone that comes to try Blazor WebAsssembly that comes from Angular, React, Vue, or any other framework is just going to laugh you out of the room when you tell them that on first load the entire site is going to be loaded in the browser.
As an example, our production site in Angular, best case scenario based on not supporting this would be over 17 megs to load in Blazor WebAssembly BEFORE first paint. Which isn't going to happen and there's absolutely 0 chance I get this by people internally even for new projects until this functionality is there. (And I strongly suspect that that will be the answer everywhere, not just my company for obvious reasons.)
Please reconsider and make this a priority for April/May 3.2 release otherwise this is DOA for 99% of users. They just don't know it yet because they're making an assumption that this is already available.
I agree with JohnGalt1717. We have a few upcoming large client projects that we were wanting to use Blazor for (and a few existing projects that we were considering refactoring to use Blazor). There is no way we can develop large web based applications on Blazor without lazy loading, it wouldn't be feasible. As much as we really want to use it, we cannot consider Blazor a SPA contender until lazy loading is added sufficiently.
For my current project, it would be great if I could load Blazor components as independent modules. I have a website where different modes will be added over time and those modes should not be coupled to the "mainproject", it should be possible that different independent people develop them and that they can be added to the site without redeploying the whole site. I imagine it a bit like an API controller: There is a request to the server /GetAppMode("identifier") and it then loads the module "identifier" and returns it to the client.
This is the Micro frontends pattern and this is defiantly something my team would require.
Different teams (services) would be able to updates their own assembly and this would be dynamically loaded into the host application, component would be able to talk to each other via events this is the dream would also be great if assemblies could be loaded from different sub domains
Hi all Blazor eager developers, I've created assembly lazy load feature for my project. Lazy load works on page level. If you like to check it, navigate to https://github.com/MarekPokornyOva/BlazorLazyLoad. That concept might also help to put hands on and clarify the feature usage and expectations (as danroth27 asked for), at least until this is supported out-of-the-box.
Hi everyone, good news for you all! I've been following this thread closely from the beggining, and decided to create a fully fledged Blazor Lazy Loading library (wasm, server, prerendering) inspired by the work @MarekPokornyOva has done.
Just by adding a NuGet package the lib automatically orchestrates a build-time manifest generator, build-time dll bundling (using StaticWebAssets), client side manifest consumption, assembly locators based on the manifests, assembly loaders, etc.
V1 will ship with 2 razor components: <Lazy Name="ComponentName" />
and <LazyRouter ... />
which automatically take care of loading the required DLLs/PDBs for you and rendering the components/pages.
It also includes full assembly isolation (using AssemblyLoadContext) for the ServerSide (required for horizontally scaling).
I'm in the last stages of the development and currently looking for a small-ish blazor project where I can contribute so I can implement Lazy Blazor on it.
All the work has been done in here: https://github.com/isc30/blazor-lazy-loading Will also inform when I release the first stable version!
Hi everyone, good news for you all! I've been following this thread closely from the beggining, and decided to create a fully fledged Blazor Lazy Loading library (wasm, server, prerendering) inspired by the work @MarekPokornyOva has done.
Will also inform when I release the first stable version!
Could you write a bit more technical description how it works? As much detailed as possible. Thank you.
@bkv143 Could you write a bit more technical description how it works? As much detailed as possible. Thank you.
Absolutely! It's already in the roadmap to get as much documentation as I can (diagrams, etc) after implementing all the core features.
I will try to give a small overview now:
When
BlazorLazyLoading.Module
is referenced from aRazorLib
project, it will generate 2 things at build time:wwwroot/_lazy/
containing all the required DLLs and PDBs andwwwroot/lazy.json
which is a simple manifest file describing what the module contains (components, routes, etc). The generated manifest will also be generated for directly referencedRazorLib
projects too, so you can either have completely isolated modules OR a single module aggregating multiple projects.When
BlazorLazyLoading.Components
is referenced from any place, you can use the<Lazy>
and<LazyRouter>
to automatically download the DLLs and render the components.When calling
.AddLazyLoading(...)
you need to pass some entry-point module names. When a lazy component is used it will fetch the manifests from these modules (_lazy.json
) and inspect them to know where the components/routes exist (in which DLLs). Then, it will fetch the required DLLs and load them. After that, it will render your page/component using a bit of reflection :)In case you want to manually load an assembly you can also do it by injecting
IAssemblyLoader
and callingLoadAssemblyByNameAsync
, which will fetch it for you and load it into the current assembly context
It includes full lazy loading support for Wasm, Prerendering, BlazorServer... even DualMode! Lazy loading includes named components and routes (with parameters).
Please check it out https://github.com/isc30/blazor-lazy-loading
and the docs https://github.com/isc30/blazor-lazy-loading/wiki
Great work doing something that Microsoft shouldn't be shipping Blazor without. Hope they work with you to have a migration plan when .net 5 comes out with proper support baked in.
@danroth27 - This issue is to lazy load an "Area" as a way to improve performance of a large application. Would it be possible to extend this concept to "modules" to enable some form of extensibility? As an example, I have a website that allows the upload of widgets (javascript) that asp.net core dynamically loads into the dom enabling extensibility of the user interface.
I'd love to be able to do this in a good way using Blazor too, to enable customised features for specific clients and not others, or even allow customers to add their own widgets meaning the website only know about it's existing through something like an API with the module and details about that module and wouldn't know anything at build time other than that there might be something. We loop through a widget list and add it to a widget canvas basically.
@radderz, maybe you'd try https://github.com/MarekPokornyOva/BlazorLazyLoad - see \Samples\01\BlazorApp\Pages\LazyComponent for component level lazy loading.
@MarekPokornyOva I am talking about the built in version done by MS for .NET 5, I did check your github repo, and it may be possible to do that, but I haven't started a production project yet so would prefer a built in way once we do.
I did however check your repo earlier, how would you go about including an unknown module at runtime? I.e. not it isn't a known assembly at build time so the manifest approach wouldn't work. There was no documentation on how to use the "Raw" style where you manually do things yet.
@radderz The manifest approach is completely extensible, it doesn't need to rely on static files 😄
You can achieve what you suggest by specifying a custom IAssemblyLocator
(where to find the DLLs) and IManifestLocator
(where to download the manifest JSON). These could be both AspNetCore endpoints.
This approach would also work well with <Lazy>
and <LazyRouter>
since they rely on these interfaces too.
Also, the assemblies can run a Startup
when they load to register new implementations on runtime (f.e. ITagHelperComponent).
Please remember that blazor-lazy-loading is a library, it will give you the building blocks to create a runtime module system on top of it easily (which is more framework-ish).
Writing the "Going Raw" documentation is top priority atm, but please open a ticket in the repository so we can discuss your needs and which documentation would help you.
You can also have a look at these examples, for loading modules manually:
Maybe we can work together on crafting a "demo"+documentation that does what you are suggesting? 😄
@radderz The manifest approach is completely extensible, it doesn't need to rely on static files 😄
You can achieve what you suggest by specifying a custom
IAssemblyLocator
(where to find the DLLs) andIManifestLocator
(where to download the manifest JSON). These could be both AspNetCore endpoints.
Sounds like it may work for what we are doing in JS, that's exactly the concept I meant so it's good to see it being possible even if MS doesn't do it for .NET 5.0. Good work, I'll create a issue in your repo with the use case example as although I may not use it right now it might help you provide good documentation for others doing similar things!
@danroth27 Will issue (11212) Nested Routing In Blazor be fixed as part of this ?
@AmarjeetBanwait Not really. I'd recommend adding any scenarios/thumbs-up you have on the original issue for nested routes.
Oqtane ( https://github.com/oqtane/oqtane.framework ) is a modular framework built on Blazor and it already supports dynamic loading of "modules" created as razor class libraries ( including dealing with CSS and JS loading concerns ). However the current challenge we encountered with lazy loading is not related to dynamically loading assemblies or instantiating razor components... it is related to moving beyond "hello world" scenarios and creating a real world data-centric client/server plug-in module. A data-centric client/server module will have a Web API Controller which the razor components will call to retrieve data from the server. However it appears that the only way to load a Web API Controller dynamically is during Startup using mvcBuilder.PartManager.ApplicationParts.Add(part); This is an issue for lazy loading as it means that these assemblies must all be identified and loaded during startup and cannot be loaded on demand. Will it be possible in MVC 5.0 to dynamically add ApplicationParts outside of Startup?
Thanks for participating in this thread everyone!
We'll be shipping support for lazy-loading as part of the upcoming preview8 release. Some follow-ups will be shipped in rc1, too. Once preview8 ships, you'll find docs on lazy-loading in Blazor at docs.microsoft.com.
Looking forward to hearing your feedback on the feature!
@captainsafia, when preview 8 will be released?
@Dennis-Petrov According to the Milestones section, it is scheduled for August 20, 2020.
@danroth27 Do you already have a few more details available for how this might work on a conceptual level? E.g. is it envisioned that each lazy-loaded area could be in a separate project/assembly?
I'm always interested in scalability beyond the typical demo projects used at conferences and in tutorials... ;-)