Angular - Hot Module Replacement (HMR) is a Webpack feature to update code in a running app without refreshing the browser.

Since Angular version 11 it is build in the Angular CLI and very easy to use / configure.

Set "hmr" in angular.json.

"serve": {
  ...
  "configurations": {
    "development": {
      "browserTarget": "my-app:build:development",
      "hmr": true
    }
  },
  ...
}

Now comes the important part where I was banging my head against the wall ??.

My old main.browser.ts (or just main.ts if you are not using SSR).

document.addEventListener('DOMContentLoaded', () => {
  platformBrowserDynamic()
    .bootstrapModule(AppBrowserModule)
    .catch(console.error);
});

Updated to this.

function bootstrap() {
  platformBrowserDynamic()
    .bootstrapModule(AppBrowserModule)
    .catch(console.error);
};

if (document.readyState === 'complete') {
  // Required for HMR:
  bootstrap();
} else {
  document.addEventListener('DOMContentLoaded', bootstrap);
}

This actually makes sense.
HRM will execute the main.browser.ts again but the DOMContentLoaded event will only trigger after a browser refresh.

Happy Coding!

ng serve