Act when lazy loaded module is destroyed

邮差的信 提交于 2019-12-03 15:19:41

As of Angular 6 modules never unload.

The router currently doesn't check if a module has been destroyed after lazy loading it. So even if you get the NgModuleRef and call destroy manually the router still thinks it's loaded. So it won't lazy load it a second time.

The router just loads the module but does not manage it's life-cycle. Even if you could destroy a module it would not free much memory. Lazy loaded modules are managed by WebPack bundles that are loaded with SystemJS. Once they are loaded they stay in memory. Even if Angular destroy the module instance the source code for the bundle is still in SystemJS's memory cache of loaded bundles.

This problem extends to vendor libraries. If you have a lazy loaded module that uses a third-party graphics library like D3, then that vendor library will be loaded and you can't unload it.

If you need to have providers that exist only for specific routes, then you should be using view providers.

@Component({
     ...
     viewProviders: [
         LazyFeatureService
     ]
})
export class MyLazyComponent {}

When you use the above component as a router component, then the service LazyFeatureService is created when the module is lazy loaded, but when the component is destroyed the service is also destroyed. The next time the user visits the lazy route the service will get created again.

Update:

The reason is I need to reset the shared service configuration. Basically, I have certain configuration data for the application, and I need to override it for the lazy-loaded module, but put it back once the user is not in the module.

You can achieve this by using the canActivate and canDeactivate handlers in the route.

In your route config for the lazy module create a top-level route to handle activations.

const routes: Routes = [
    {
        path: '',
        canActivate: [ConfigActivator],
        canDeactivate: [ConfigActivator],
        children: [
            // move the routes here
        ]
    };

You can then define the activator like this.

 @Injectable()
 export class ConfigActivator implement CanActivate, CanDeactivate<any> {
       public constructor(private config: MyConfigService) {
       }

       public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
           this.config.lazyModuleLoaded();
           return true;
       }

       public canDeactivate(component: any, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot, nextState?: RouterStateSnapshot): boolean {
           this.config.lazyModuleUnloaded();
           return true;
       }
 }

The above will call methods on the service to tell it when it should update the config based upon the change in router state. Since this is on a top-level route for the lazy module it will only be triggered when the route is activated, and when the route leaves that path.

Modules are not destroyed after they are lazy loaded but you can implement OnDestroy on the component that the module loads.

Whichever component in your module that has the router outlet is what is created and destroyed as you navigate.

What component hosts the

<router-outlet></router-outlet>

And in the TypeScript for that component implement OnDestroy and it will call the ngOnDestroy method.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!