J'ai créé un nouveau projet angular et configuré HMR comme expliqué ici: https://github.com/angular/angular-cli/wiki/stories-configure-hmr =
Le projet contient le composant principal (parent) qui a router-outlet
et des liens vers 3 composants enfants chargés paresseusement.
Remarque: j'utilise également RouteReuseStrategy
personnalisé mais cela n'a aucun effet sur le HMR pour autant que j'ai testé.
Quel que soit le fichier que je modifie - .html ou .ts (parent/enfants), l'application entière se recharge.
J'ai mis en place un dépôt de base qui peut être trouvé ici: https://github.com/ronfogel/demo-hmr
Ce comportement est attendu, je vais essayer d'expliquer ce qui se passe.
Le remplacement de module à chaud que angular angulaire a mis en place est vraiment juste en train de redémarrer toute l'application d'une manière plus générique et avec le support de plusieurs racines d'application, mais si vous mettez les abstractions de côté, il suffit de supprimer app-root
tag, en l'ajoutant à nouveau et en amorçant à nouveau AppModule
, donc toute l'application change:
export const hmrBootstrap = (
// webpack stuff
module: any,
// bootstrap is AppModule bootstrapper
bootstrap: () => Promise<NgModuleRef<any>>
) => {
let ngModule: NgModuleRef<any>;
module.hot.accept();
// bootstraps AppModule ecery time a HMR is needed
// sets ngModule equal to AppModule if successful (unnecessary)
bootstrap().then(mod => (ngModule = mod));
module.hot.dispose(() => {
// next two lines get native element for all `app-root` tags
// that exist in `index.html`
const appRef: ApplicationRef = ngModule.injector.get(ApplicationRef);
const elements = appRef.components.map(c => c.location.nativeElement);
// I will share createNewHosts code below it's nothing fancy just
// the simple add and delete i mentioned
const makeVisible = createNewHosts(elements);
//destroy the current AppModule and finalize deletion
ngModule.destroy();
makeVisible();
});
};
C'est ce que j'utilise pour le dernier Angular, qui fonctionne très bien. Vous pouvez l'essayer ...
// main.ts
import { bootloader, createInputTransfer, createNewHosts, removeNgStyles }
from '@angularclass/hmr/dist/helpers'; // For correct treeshaking
if (environment.production) {
enableProdMode();
}
type HmrModule<S> = { appRef: ApplicationRef }
type HmrNgrxModule<S, A> = HmrModule<S> & {
store: { dispatch: (A) => any } & Observable<S>,
actionCreator: (s: S) => A
}
const isNgrxModule = <S, A, M extends HmrNgrxModule<S, A>>
(instance: HmrModule<S> | HmrNgrxModule<S, A>): instance is M =>
!!((<M>instance).store && (<M>instance).actionCreator);
function processModule<S, A, M extends HmrModule<S> | HmrNgrxModule<S, A>>(ngModuleRef: NgModuleRef<M>) {
const hot = module['hot'];
if (hot) {
hot['accept']();
const instance = ngModuleRef.instance;
const hmrStore = hot['data'];
if (hmrStore) {
hmrStore.rootState
&& isNgrxModule(instance)
&& instance.store.dispatch(instance.actionCreator(hmrStore.rootState));
hmrStore.restoreInputValues && hmrStore.restoreInputValues();
instance.appRef.tick();
Object.keys(hmrStore).forEach(prop => delete hmrStore[prop]);
}
hot['dispose'](hmrStore => {
isNgrxModule(instance) && instance.store.pipe(take(1)).subscribe(s => hmrStore.rootState = s);
const cmpLocation = instance.appRef.components.map(cmp => cmp.location.nativeElement);
const disposeOldHosts = createNewHosts(cmpLocation);
hmrStore.restoreInputValues = createInputTransfer();
removeNgStyles();
ngModuleRef.destroy();
disposeOldHosts();
});
}
else {
console.error('HMR is not enabled for webpack-dev-server!');
console.log('Are you using the --hmr flag for ng serve?');
}
return ngModuleRef;
}
const bootstrap = () => platformBrowserDynamic().bootstrapModule(AppModule);
const hmrBootstrap = () => bootloader(() => bootstrap().then(processModule));
environment.hmr
? hmrBootstrap()
: bootstrap();
// app.module.ts
@NgModule({ ... })
export class AppModule {
constructor(public appRef: ApplicationRef) { ... }
}
La configuration HMR
fonctionnera également avec le magasin Ngrx, si vous êtes dans ce genre de choses. Vous pouvez cependant omettre le code de gestion Ngrx.
Espérons que cela aide un peu :-)