KarimTayie / angular-hmr-lazy-components

This example shows how Angular HMR can be used to automatically reload lazy routes and lazy (dynamically-loaded) components. This can be extremely helpful for large Angular apps that take a while to JIT compile when they reload.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

angular-hmr-lazy-components

This example shows how Angular HMR can be used to automatically reload lazy routes and lazy (dynamically-loaded) components. This can be extremely helpful for large Angular apps that take a while to JIT compile when they reload.

Notice in the animation below that moments after a change is made in the a.component.ts source code, just the "A" components already showing in the app are reloaded. Image of example in action

Reloading Lazy Routes

How It Works

Most of the magic is in hmr-module-helper.ts. Each module that is going to be lazy-loaded through the router will use this helper class to enable HMR for that module. Here's how this is used in the c module:

  export class CModule {
    constructor(moduleRef: NgModuleRef<CModule>) {
      HmrModuleHelper.enableHmrRouterNgModule(module, moduleRef);
    }
  }
  
  HmrModuleHelper.enableHmrNodeModule(module);

Reloading Dynamically-Loaded Components

How It Works

Reloading dynamically-loaded components takes a little bit more.

  • dynamic-component.service.ts - This service is responsible for dynamically loading and opening components, keeping track of what components are open, closing components, and reloading components.

  • hmr-module-helper.ts. Each module that is going to be dynamically loaded will use this helper class to enable HMR for that module. This also wires things up with the DynamicComponentService to destroy and reload the components when the module is hot-reloaded. Here's how this is used in a module:

    export class AModule {
      constructor(moduleRef: NgModuleRef<AModule>) {
        HmrModuleHelper.enableHmrDynamicNgModule(module, moduleRef);
      }
    }
    
    HmrModuleHelper.enableHmrNodeModule(module); 
    

Instructions

Besides the above files, there are a few other things to point out:

  • You'll need to list each module that you want to dynamically load in the lazyModules setting of your angular.json file:

    "lazyModules": [
      "src/app/lazy-components/a/a.module",
      "src/app/lazy-components/b/b.module"
    ]
    
  • You'll need to enable hmr in serve section of your angular.json file:

    "options": {
      "browserTarget": "demo:build",
      "hmr": true,
      "hmrWarning": false
    },
    
  • Setup your environments files so you can detect in code if hmr is on. Details can be found on the Angular CLI wiki.

  • If you aren't using/importing the @angular/router, you'll need to configure a provider for the NgModuleFactoryLoader in your app.module.ts:

    providers:    [
      {provide: NgModuleFactoryLoader, useClass: SystemJsNgModuleLoader},
      DynamicComponentsService
    ],
    

Remarks

  • Because the DynamicComponentsService uses the components' selectors, all of the dynamic loading works in a Prod (AOT) build.
  • You can't run this example on StackBlitz, as it doesn't seem to honor the lazyModules setting in the angular.json file.

About

This example shows how Angular HMR can be used to automatically reload lazy routes and lazy (dynamically-loaded) components. This can be extremely helpful for large Angular apps that take a while to JIT compile when they reload.

License:MIT License


Languages

Language:TypeScript 86.1%Language:HTML 7.2%Language:JavaScript 4.1%Language:CSS 2.6%