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.
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 takes a little bit more.
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
HmrModuleHelper.enableHmrNodeModule(module);
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 ],