Code Monkey home page Code Monkey logo

blazor-lazy-loading's People

Contributors

dependabot[bot] avatar isc30 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

blazor-lazy-loading's Issues

Lazy component improvements

  • Ability to specify the module manually when using FullType
  • Ability to pass arbitrary Parameters to the wrapped component

Linker adds unused dependencies as boot

The linker in Blazor WASM is including dependencies that aren't in use (in normal scenarios these would be stripped out by the compiler, which is what happens with the linker disabled (ok)).

When adding a reference (RCL project/nuget) to a project with Microsoft.AspNetCore.Components.WebAssembly.Build and BlazorWebAssemblyEnableLinking set to true, the linker will add the dependency project as a boot dependency inside blazor.boot.json even if it's not used at all.

If this reference is not used, the linker should detect it and not add it as a boot project. I suspect the problem is somewhere where we take the linker output and enumerate the blazor binaries based on it.

This issue doesn't happen with BlazorWebAssemblyEnableLinking disabled (the unused project is not even inside _framework/_bin).

To Reproduce

Please follow the steps to get this reproduced on your own repository.
In order to check the bug, this minimal example repository with the bug can be used.

Properly Working Example: With no Linker

  1. Create a Blazor WASM project (host)
  2. Add <BlazorWebAssemblyEnableLinking>false</BlazorWebAssemblyEnableLinking>
  3. Create a RCL project (lib) with a Component and wwwroot/test.css as StaticWebAsset
  4. Reference lib from host and use the Component from it
  5. Build and Run
  6. The DLL of lib appears inside blazor.boot.json and gets downloaded during startup (ok)
  7. Navigate to _content/lib/test.css and see that the StaticWebAsset is available (ok)
  8. Remove the runtime usage of lib by not using the Component anymore so the compiler strips it out
  9. The DLL of the project is no longer inside blazor.boot.json and doesn't get downloaded during startup (ok)
  10. The StaticWebAsset _content/lib/test.css is still available (ok)

Buggy Example: With Linker enabled

  1. Use the project from the working example
  2. Change it to use <BlazorWebAssemblyEnableLinking>true</BlazorWebAssemblyEnableLinking>
  3. Reference lib from host and use the Component from it
  4. Build and Run
  5. The DLL of lib appears inside blazor.boot.json and gets downloaded during startup (ok)
  6. Navigate to _content/lib/test.css and see that the StaticWebAsset is available (ok)
  7. Remove the runtime usage of lib by not using the Component anymore so the compiler strips it out
  8. The DLL of the project is still inside blazor.boot.json and still gets downloaded during startup (fail)
  9. The StaticWebAsset _content/lib/test.css is still available (ok)

Further technical details

  • ASP.NET Core version: 3.2.0-rc1.20223.4
  • dotnet version: 3.1.201

Comments

This is a rather big bug. When including a NuGet package and using a small portion of it, the linker will still add every sub-reference, even if not used and the DLL could be skipped.

This should still preserve StaticWebAssets from the projects that don't need a runtime.

AssemblyInitializer (Startup)

We need to have a way to call lazily Startup classes after lazy loading.
I don't have a full idea on how this will work but I would maintain 2 actions:

  • Configure - adds services to IServiceCollection
  • Initialize - after configuring, it initializes the services (if extra steps are required)

Configure should be called on all the dependencies in the same order as they are loaded into memory.
Initialize should be called after ALL assemblies have been configured, not sure about the order.

Rework the Module system

  • Stamp the Modules with [BlazorLazyLoadingModule] to detect nested modules at build time
  • Generate the lazy json as a build artifact and copy it later to wwwroot
  • Implement dynamic ModuleHints
  • Implement events for ModuleHints so we can fetch automatically after being discovered
  • When generating a manifest, check if the assembly is a Module and if that's the case, read it's manifest and append it to the existing one. This way we "aggregate" nested manifests into a single file without losing their private properties like BLLManifestAssemblies, etc.
  • Read lazy.json from Modules and append the generated manifest to that content
  • Implement a custom manifest generator system so users can add their own stuff to the generated manifest

Rename nuget packages

After introducing ModulesHost concept, I should rename all the Nuget packages to:

  • BlazorLazyLoading.WasmHost: WebAssembly Server
  • BlazorLazyLoading.ServerHost: BlazorServer Server
  • BlazorLazyLoading.ModulesHost: Module aggregator/manifest generator
  • BlazorLazyLoading.Components: Razor components to enable lazy loading (+ )

Non referenced RCLs (RazorClassLibraries)

Hi,

I am working through the wiki docs and thank you for taking the time to write some docs. I realize these are early days, so I would like to ask:

For a wasm client, can one create RCL modules that are not directly referenced by the wasm project (or a modulesHost project), kind of a "disconnected" setup where I could then build a module from a separate solution and deploy the output to some common modules folder?

Support new .NET 5 lazy assembly loader

Blazor team did a lot of work to introduce a partial implementation of the lib into blazor itself. This means that the LazyAssemblyLoader is a native part of blazor now! When .NET 5 RC1 is released, this library should shrink and reuse as much as it can from the official lazy loading support.

Going Raw

  • Configurable IAssemblyLocator
  • Configurable IModuleLocator
  • "Going Raw" documentation

Only RCL-based components or entire pages?

Hi Ivan, this is an interesting system you've built.

I'm interested in runtime loading of page-based razor component libraries (Blazor server-side), but if I'm reading your readme and wiki correctly, it sounds like this only operates at the component level. Is that accurate?

I suspect page-content RCLs would require somehow registering the newly-loaded page with the router. I saw one of your comments in a closed issue that you were going to ask MS about opening up their router, did you get anywhere with that?

Basically we're planning to build a gigantic (enterprise) system, hundreds of pages, and we're designing around a base "frame" that can host arbitrary content that ideally isn't known at build-time. (We have the beginnings of a page-based system where the "frame" pages are basically two-line stubs -- the @page directive and a <component> tag that ties to a referenced RCL, it's that need to build One Giant Solution that I'm trying to break.) I was trying to imagine different ways to discover/load that content at runtime -- and unload, so we don't just accumulate assemblies as the user navigates around in the app all day long.

Have you considered anything along these lines? All I've found so far is that Oqtane content management system, but that's too much tie-in for us.

Binaries generation

We need to have the targets to copy the library DLLs as part of some other package

Use the library in BlazorBoilerPlate?

Hi,
I discovered your project reading dotnet/aspnetcore#5465
and now I am starting to understand how it works because in my branch https://github.com/enkodellc/blazorboilerplate/tree/development I am trying to modularize the UI, but at the moment I used hacks because in my webassembly version I do not know how to dinamically load modules (see https://github.com/enkodellc/blazorboilerplate/blob/development/src/Client/BlazorBoilerplate.Client/Program.cs)

With the blazor server version I can load modules at runtime and use the pages inside without any problem, but I have to include an unwanted reference to them only if the have a wwwroot folder.
So studying your repository I plan to remove module references in (https://github.com/enkodellc/blazorboilerplate/blob/development/src/Server/BlazorBoilerplate.Server/BlazorBoilerplate.Server.csproj)

Good work!

Central ModulesHost Project

The self-hosting module idea is nice, until you start adding dependencies between them. In that case, the amount of generated DLLs becomes massive.

It's better to have a single "source of truth" from where the lazy DLLs are loaded.

This will make the migration to LazyBlazor simpler and simplify custom manifest generation in the future too.

Support Components from NuGet packages

Mentioned in #42

  • Check if referencing the package generates the metadata properly
  • (possibly) Check if adding the assembly to BLLManifestGeneratorAssemblyNames works
  • Document the solution

Unable to build Demo project - The "ResolveBlazorRuntimeDependencies" task failed unexpectedly

Unable to build Demo solution. The build process failed with error:

Error MSB4018 The "ResolveBlazorRuntimeDependencies" task failed unexpectedly.
System.IO.FileNotFoundException: Could not load file or assembly 'WasmHost.dll' or one of its dependencies. The system cannot find the file specified.
File name: 'WasmHost.dll' ---> System.IO.FileNotFoundException: The system cannot find the file specified. (Exception from HRESULT: 0x80070002)
at System.Reflection.AssemblyName.nGetFileInformation(String s)
at System.Reflection.AssemblyName.GetAssemblyName(String assemblyFile)
at Microsoft.AspNetCore.Components.WebAssembly.Build.ResolveBlazorRuntimeDependencies.ResolveRuntimeDependenciesCore(String entryPoint, IEnumerable1 applicationDependencies, IEnumerable1 monoBclAssemblies)
at Microsoft.AspNetCore.Components.WebAssembly.Build.ResolveBlazorRuntimeDependencies.Execute()
at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.d__26.MoveNext()

WasmHost	C:\Users\BKV\.nuget\packages\microsoft.aspnetcore.components.webassembly.build\3.2.0-preview4.20210.8\targets\Blazor.MonoRuntime.targets	324	

NuGet package

I need to generate 3 NuGet packages (at least)

  • BlazorLazyLoading.Module (msbuild targets)
  • BlazorLazyLoading.Server
  • BlazorLazyLoading.Wasm

PR for AspNetCore making Routing utilities public

Implementing a custom Router is a pain ATM, due to all the route matching utilities being internal and the handlers being constrained to Type.

  • The routing utilities (RouteContext, RouteEntry, RouteTable, ...) should be public.
  • RouteContext.Handler needs to be of type object to allow implementing custom handlers.

Unhandled exception rendering component: Cannot consume scoped service 'System.Net.Http.HttpClient' from singleton BlazorLazyLoading.Abstractions.IContentFileReader

      Unhandled exception rendering component: Cannot consume scoped service 'System.Net.Http.HttpClient' from singleton 'BlazorLazyLoading.Abstractions.IContentFileReader'.
System.InvalidOperationException: Cannot consume scoped service 'System.Net.Http.HttpClient' from singleton 'BlazorLazyLoading.Abstractions.IContentFileReader'.
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitScopeCache(ServiceCallSite scopedCallSite, CallSiteValidatorState state)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.CallSiteValidatorState, Microsoft.Extensions.DependencyInjection, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.Type, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].VisitCallSite(ServiceCallSite callSite, CallSiteValidatorState argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteValidatorState state)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.CallSiteValidatorState, Microsoft.Extensions.DependencyInjection, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.Type, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].VisitCallSiteMain(ServiceCallSite callSite, CallSiteValidatorState argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitRootCache(ServiceCallSite singletonCallSite, CallSiteValidatorState state)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.CallSiteValidatorState, Microsoft.Extensions.DependencyInjection, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.Type, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].VisitCallSite(ServiceCallSite callSite, CallSiteValidatorState argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitConstructor(ConstructorCallSite constructorCallSite, CallSiteValidatorState state)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.CallSiteValidatorState, Microsoft.Extensions.DependencyInjection, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.Type, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].VisitCallSiteMain(ServiceCallSite callSite, CallSiteValidatorState argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.VisitRootCache(ServiceCallSite singletonCallSite, CallSiteValidatorState state)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.CallSiteValidatorState, Microsoft.Extensions.DependencyInjection, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.Type, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].VisitCallSite(ServiceCallSite callSite, CallSiteValidatorState argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.ValidateCallSite(ServiceCallSite callSite)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.Microsoft.Extensions.DependencyInjection.ServiceLookup.IServiceProviderEngineCallback.OnCreate(ServiceCallSite callSite)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.CreateServiceAccessor(Type serviceType)
   at System.Collections.Concurrent.ConcurrentDictionary`2[[System.Type, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Func`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope, Microsoft.Extensions.DependencyInjection, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60],[System.Object, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetOrAdd(Type key, Func`2 valueFactory)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at Microsoft.AspNetCore.Components.ComponentFactory.<>c__DisplayClass6_0.<CreateInitializer>g__Initialize|2(IServiceProvider serviceProvider, IComponent component)
   at Microsoft.AspNetCore.Components.ComponentFactory.PerformPropertyInjection(IServiceProvider serviceProvider, IComponent instance)
   at Microsoft.AspNetCore.Components.ComponentFactory.InstantiateComponent(IServiceProvider serviceProvider, Type componentType)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.InstantiateComponent(Type componentType)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.InstantiateChildComponentOnFrame(RenderTreeFrame& frame, Int32 parentComponentId)
   at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewComponentFrame(DiffContext& diffContext, Int32 frameIndex)
   at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewSubtree(DiffContext& diffContext, Int32 frameIndex)
   at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(DiffContext& diffContext, Int32 newFrameIndex)
   at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& diffContext, Int32 oldStartIndex, Int32 oldEndIndexExcl, Int32 newStartIndex, Int32 newEndIndexExcl)
   at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(Renderer renderer, RenderBatchBuilder batchBuilder, Int32 componentId, ArrayRange`1 oldTree, ArrayRange`1 newTree)
   at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderInExistingBatch(RenderQueueEntry renderQueueEntry)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()

In razor page

@code {
[Inject]
    private PublicViewDataService publicViewDataService { get; set; }
    private Tag[] tags;
    protected override async Task OnInitializedAsync()
    {
        tags = await publicViewDataService.tags();
    }

}

publicViewDataService

public class PublicViewDataService : INotifyPropertyChanged
    {
        private readonly IServiceProvider _serviceProvider;
        //private HttpClient Http;
        public PublicViewDataService(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private Tag[] _tags;
        public async Task<Tag[]> tags()
        {
            if (_tags == null)
            {
                using (var scope = _serviceProvider.CreateScope())
                {
                    var Http = scope.ServiceProvider.GetRequiredService<HttpClient>();
                    _tags = await Http.GetFromJsonAsync<Tag[]>("api/data/gettags");
                }
            }
            return _tags;
        }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.