wishtack / wishtack-steroids

Frontend on Steroids: Reactive Component Loader, RxJS Scavenger...
https://wishtack.io
MIT License
96 stars 16 forks source link

ng8 & ivy #183

Closed Sebush closed 4 years ago

Sebush commented 5 years ago

Hi,

is it possible to make "reactive-component-loader" ivy-ready?

enable ivy in tsconfig.json { ... "angularCompilerOptions": { "enableIvy": true } ... }

change loadChildren: './dyn.module#DynModule', // old style to loadChildren: (() => import('./dyn.module').then(m => m.DynModule)), // new style

with old pre-ivy-style i get an error:

core.js:7187 ERROR TypeError: Cannot read property 'values' of undefined at ReactiveComponentLoader._tryGetComponentType (wishtack-reactive-component-loader.js:116) at ReactiveComponentLoader. (wishtack-reactive-component-loader.js:97) at Generator.next () at fulfilled (tslib.es6.js:68) at ZoneDelegate.invoke (zone-evergreen.js:359) at Object.onInvoke (core.js:30900) at ZoneDelegate.invoke (zone-evergreen.js:358) at Zone.run (zone-evergreen.js:124) at zone-evergreen.js:855 at ZoneDelegate.invokeTask (zone-evergreen.js:391)

with new style i get an other error:

ERROR TypeError: path.split is not a function or its return value is not iterable at SystemJsNgModuleLoader.loadAndCompile (core.js:32294) at SystemJsNgModuleLoader.load (core.js:32286) at ReactiveComponentLoader. (wishtack-reactive-component-loader.js:135) at Generator.next () at tslib.es6.js:71 at new ZoneAwarePromise (zone-evergreen.js:876) at __awaiter (tslib.es6.js:67) at ReactiveComponentLoader._getModuleFactory (wishtack-reactive-component-loader.js:134) at ReactiveComponentLoader. (wishtack-reactive-component-loader.js:91) at Generator.next ()

bmarti44 commented 5 years ago

I have a PR open for converting just the reactive component loader over to ng8, but need to get feedback (I feel like there's probably more work to do there). I also upgraded the ng-dynamic-component loader (which didn't absolutely need it but makes me feel better).

meysamsahragard commented 5 years ago

Hi. Is this package ng8 ready, now? ModuleInfo only accepts loadchildern as a string, How can I use new style? Like this: loadChildren: (() => import('./dyn.module').then(m => m.DynModule))

yjaaidi commented 5 years ago

Hi there! Ng8 & IVy are making lazy loading even easier. There will be a release soon thanks to @bmarti44 + some rethinking of the library's interface to make it even easier to use.

denisyilmaz commented 5 years ago

Any timeframe when the library will be updated with ng8 and ivy support?

yjaaidi commented 5 years ago

I hope to release a new version in one week or two.

AmaelN commented 4 years ago

Hi, I'm using angular 8.2.14 I took the latest npm package 1.1.0 and I've change my lazy config as below

ReactiveComponentLoaderModule.withModule({
    moduleId: 'my-sidebar',
    loadChildren: ()=>import('src/app/shared/sidebar/sidebar.module').then(m=> m.SidebarModule)
  }),

with Ivy enabled, I'm getting the following error message on the console

ERROR TypeError: Cannot read property 'values' of undefined
    at ReactiveComponentLoader._tryGetComponentType (wishtack-reactive-component-loader.js:114)
    at ReactiveComponentLoader.<anonymous> (wishtack-reactive-component-loader.js:95)
    at Generator.next (<anonymous>)

Thanks

AmaelN commented 4 years ago

Dear friend,

Where are you at with this fix for Angular 9. Th new version of Angular (9.0.0) is out now...

It is about time to provide us with a solution

Do you need help ? what shall we do to help you out and how ?

Thanks in advance,

yjaaidi commented 4 years ago

Hi @AmaelN & everyone! The latest version 1.1.1 is IVy compatible. If it's not working, could you please share a repository with a reproduction of the issue. Thank you in advance.

Younes

tdymel commented 4 years ago

Edit: Since my system needs this banner, I disabled ivy for now. But in the readme are instructions on how to build and run the application.

@yjaaidi https://alpha.legacyplayers.com/armory Click on "Change consent" in the footer and check the console log or check it directly.

Event is bubbled to here, where it is instructed to be shown: https://github.com/Geigerkind/LegacyPlayersV3/blob/master/Webclient/src/app/component/app/app.ts

Its uses wt-lazy here: https://github.com/Geigerkind/LegacyPlayersV3/blob/master/Webclient/src/app/component/app/app.html

Reactive loader is initialized here: https://github.com/Geigerkind/LegacyPlayersV3/blob/master/Webclient/src/app/module.ts

AmaelN commented 4 years ago

Hi @yjaaidi,

Sorry for the delay but I was a bit busy.

I've just move to angular 9. I had to disable Ivy as ComponentFactoryResolver$1  doesn't contains a definition of factories. It only contains ngModule. that's why it throw the exception at (componentFactoryResolver['_factories'].values() I've used console.log() in method _tryGetComponentType(moduleRef, selector)

Without Ivy the CodegenComponentFactoryResolver contains the factories with key-values pair

I'm going to work on a short sample to help you to reproduce the issue.

Will keep you posted shortly

AmaelN commented 4 years ago

@yjaaidi ,

I've created a fresh repo from Angular v9 sample. I've added a lazy modal and a button to open the lazy modal. https://bitbucket.org/ama03/wishtack.ivy/src/master/src/app/

The wt-lazy code is at the bottom of the app-component.html https://bitbucket.org/ama03/wishtack.ivy/src/05bc1d31be6b5faa49dd949d4b3dde33987f52ee/src/app/app.component.html#lines-529

The button is at the top of app-component.html https://bitbucket.org/ama03/wishtack.ivy/src/05bc1d31be6b5faa49dd949d4b3dde33987f52ee/src/app/app.component.html#lines-343

Check the app-component.ts and the lazy module Without Ivy it is working fine. The reason of the issue is explained in my previous post...

ofirrifo commented 4 years ago

@yjaaidi I have the same issue as @AmaelN I just upgrade my project from angular 8 to 9.1 Im using "@wishtack/reactive-component-loader": "^1.1.1",

and I'm get the same error:

instrument.js:110 ERROR TypeError: Cannot read property 'values' of undefined
    at ReactiveComponentLoader._tryGetComponentType (wishtack-reactive-component-loader.js:112)
    at ReactiveComponentLoader.<anonymous> (wishtack-reactive-component-loader.js:93)
    at Generator.next (<anonymous>)
    at fulfilled (tslib.es6.js:71)
    at ZoneDelegate.invoke (zone-evergreen.js:364)
    at Object.onInvoke (core.js:41366)
    at ZoneDelegate.invoke (zone-evergreen.js:363)
    at Zone.run (zone-evergreen.js:123)
    at zone-evergreen.js:857
    at ZoneDelegate.invokeTask (zone-evergreen.js:399)
    at Object.onInvokeTask (core.js:41344)
    at ZoneDelegate.invokeTask (zone-evergreen.js:398)
    at Zone.runTask (zone-evergreen.js:167)
    at drainMicroTaskQueue (zone-evergreen.js:569)

Thanks :)

AmaelN commented 4 years ago

@ofirrifo ,

With Angular 9, if you use Ivy, then there is a functionality part of Ivy that allow you to load on demand component. I'm planning to work on it in the coming weeks and update my sample demo with it.

Follow the steps provided by Nebasal : https://netbasal.com/welcome-to-the-ivy-league-lazy-loading-components-in-angular-v9-e76f0ee2854a

Check his sample repo here : https://github.com/NetanelBasal/ivy-lazy-components

ofirrifo commented 4 years ago

@AmaelN In my case the component I'm trying to lazy load depended with some module like NGRX:

and service that should be under the module

this is how my module of the component look:

@NgModule({
  imports: [
    CoreModule,
    SomeModule,
    CommonModule,
    EffectsModule.forFeature([SomeItemsEffects]),
    StoreModule.forFeature('someItems', fromSomeItemsPanel.reducer)
  ],
  providers: [SomeService],
  exports: [SomePanelComponent],
  declarations: [SomeItemsPanelComponent, PanelItemComponent],
  entryComponents: [SomeItemsPanelComponent]
})
export class SomeItemsPanelModule {}

In this case I'm not sure if I can lazy load my component with the new IVY syntax.

Correct me if I'm wrong.

Thanks

AmaelN commented 4 years ago

I will face the same issue... Seems possible this way : https://indepth.dev/lazy-loading-angular-modules-with-ivy/

I will look in the next few days if I can find a patch to wishtack using this article.

Le mer. 1 avr. 2020 à 1:36 PM, Ofir Fridman notifications@github.com a écrit :

@AmaelN https://github.com/AmaelN In my case the component I'm trying to lazy load depended with some module like NGRX:

  • EffectsModule.forFeature([SomeItemsEffects]),
  • StoreModule.forFeature('someItems', fromSomeItemsPanel.reducer)

and service that should be under the module

this is how my module of the component look:

@NgModule({ imports: [ CoreModule, SomeModule, CommonModule, EffectsModule.forFeature([SomeItemsEffects]), StoreModule.forFeature('someItems', fromSomeItemsPanel.reducer) ], providers: [SomeService], exports: [SomePanelComponent], declarations: [SomeItemsPanelComponent, PanelItemComponent], entryComponents: [SomeItemsPanelComponent] }) export class SomeItemsPanelModule {}

In this case I'm not sure if I can lazy load my component with the new IVY syntax.

Correct me if I'm wrong.

Thanks

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/wishtack/wishtack-steroids/issues/183#issuecomment-607390034, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEB46ILQQ3ZT4ZEETETEKPTRKN3Q5ANCNFSM4HSIPAHA .

AmaelN commented 4 years ago

Okay @ofirrifo ,@yjaaidi and others

### FOR THE FIX : ALL LAZY LOAD MODULE MUST HAVE A BOOTSTRAP COMPONENT

Here is the fix

Method to change _tryGetComponentType under node_modules\@wishtack\reactive-component-loader\__ivy_ngcc__\dist\reactive-component-loader\fesm2015

_tryGetComponentType(moduleRef, selector) {
        /** @type {?} */

        const componentFactoryResolver = moduleRef.componentFactoryResolver;            
    /** @type {?} */
      // NOT IVY CONDITIONAL INCLUDED
      if (componentFactoryResolver['_factories']) {
        const componentFactory = Array.from((/** @type {?} */ (componentFactoryResolver['_factories'].values())))
          .find((/**
         * @param {?} _componentFactory
         * @return {?}
         */
            _componentFactory => _componentFactory.selector === selector));
        if (componentFactory == null) {
          throw componentNotFoundError(selector);
        }
        return componentFactory.componentType;
      }
      //FIX -- IVY v9 
      var component = componentFactoryResolver.resolveComponentFactory(moduleRef._bootstrapComponents[0]);     
      return component.componentType;
    }
ofirrifo commented 4 years ago

@AmaelN thanks for the fast response :) I will check it tomorrow.

are you going to push the fix and publish a new version ?

AmaelN commented 4 years ago

@ofirrifo , I'm not the owner of the project. i'm like you a simple user of it so I cannot push pull request as @yjaaidi didn't provided me privilege to do so...

@yjaaidi,

Here is the fix in reactive-component-loader.service.ts

Could you push a new version, please...

private _tryGetComponentType(moduleRef, selector: string) {

        const componentFactoryResolver = moduleRef.componentFactoryResolver;
        if (componentFactoryResolver['_factories']) {
          const componentFactory = Array.from(
            componentFactoryResolver['_factories'].values() as Array<ComponentFactory<any>>
          )
            .find(_componentFactory => _componentFactory.selector === selector);

          if (componentFactory == null) {
            throw componentNotFoundError(selector);
          }

          return componentFactory.componentType;
        }
        // IVY way using bootstrap Component
        var component = componentFactoryResolver.resolveComponentFactory(moduleRef._bootstrapComponents[0]);
        return component.componentType;
    }
ofirrifo commented 4 years ago

@AmaelN Thank :) I follow your instruction for replace reactive-component-loader\fesm2015 and add the bootstrap and it do work perfect.

if @yjaaidi not going to update this repo maybe I should clone his project and fix it as new library

yjaaidi commented 4 years ago

Hi everyone!

@edbzn just provided a fix through the pull request and I released it as 1.1.2. This should fix your issue.

If you have any issue, don't hesitate to send a Pull Request. Everyone has the permission to make a PR like @edbzn did and I'll be more than glad to merge your contributions 😉.

This library was made to solve two issues:

  1. Lazy load components without the router. Thanks to IVy, things are way easier now.
  2. Passing inputs and outputs to the dynamically injected components. That is why this library is based on ng-dynamic-component.

As things have evolved now, we are thinking about creating a new library to make dynamic component injection easier.

cc. @AmaelN @ofirrifo