HMR & Ionic 4 — A better live-reload
I originally was annoyed with how Ionic 4 handles live-reloading. I always felt like the reloads would take forever, even for a small and simple change. So I decided to do some Googling and learned of Hot Module Reload (HMR) which only recompiles the files that you have recently changed. This results in nicer and faster development experiences.
Getting Started
Start off by installing the HMR dependency: npm install — save-dev @angularclass/hmr
Next, create a new environment file called environment.hmr.ts
you can add in any extra details you have in your other environment.ts
files but this is at the very least what it should look like:
export const environment = {
production: false,
hmr: true
};
Next, in both environment.prod.ts
and environment.ts
files, add hmr:false
opposite of the environment.hmr.ts
file.
Next, in your angular.json
file, you’ll need to alter it so that it looks something like the following:
"build": {
"configurations": {
...
"hmr": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.hmr.ts"
}
]
}
}
},
...
"serve": {
"configurations": {
...
"hmr": {
"hmr": true,
"browserTarget": "app:build:hmr"
}
}
}
Adding in the appropriate types:
In your tsconfig.app.json
file make sure to add the node
type into the types
array.
{
...
"compilerOptions": {
...
"types": ["node"]
},
}
And install node types it if you haven’t already:npm install @types/node
Configuring hmr.ts
We’ll now need to create a file called hmr.ts
which we’ll pull under src
it should be the following:
import { ApplicationRef, NgModuleRef } from '@angular/core';
import { createNewHosts } from '@angularclass/hmr';
export const hmrBootstrap = (module: any, bootstrap: () => Promise<NgModuleRef<any>>) => {
let ngModule: NgModuleRef<any>;
module.hot.accept();
bootstrap().then(mod => ngModule = mod);
module.hot.dispose(() => {
const appRef: ApplicationRef = ngModule.injector.get(ApplicationRef);
const elements = appRef.components.map(c => c.location.nativeElement);
const makeVisible = createNewHosts(elements);
ngModule.destroy();
makeVisible();
});
};
Changing main.ts
One of the last steps to get this to work is to alter our main.ts
file to use HMR
import { hmrBootstrap } from './hmr';
...if (environment.hmr) {
if (module[ 'hot' ]) {
hmrBootstrap(module, bootstrap);
} else {
console.error('HMR is not enabled for webpack-dev-server!');
console.log('Are you using the --hmr flag for ng serve?');
}
} else {
bootstrap().catch(err => console.log(err));
}
And the final step is to alter our package.json file scripts to handle the new setting. I changed the default start
script, but you can create a new one if you so choose.
"scripts": {
"start": "ng serve --configuration hmr",
...
},
And that’s it! This article was only made possible because of the awesome writeup and documentation of how HMR works by the Angular CLI team. It’s an underknown setting that really helps development in Ionic 4. Check out some of my other articles for more useful solutions within the Ionic framework.
Questions?
You can find me on:
- GitHub: https://github.com/bengejd/
- Medium: https://medium.com/@JordanBenge
Who am I? My name is Jordan Benge, I am a Software Developer who loves helping others and contributing to Open-Source. I’ve been working in the Ionic Framework since Ionic 1, and have tried to keep up to date on the latest and greatest when it comes to Hybrid Mobile App Development.