PatrickJS / angular-hmr

:fire: Angular Hot Module Replacement for Hot Module Reloading

Home Page:https://patrickjs.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support for Angular 7?

Epono opened this issue · comments

Hi,

I'm using Angular 7 and I followed these instructions, but states are not saved.
Does it support Angular 7 yet? Is there something missing from the documentation? Or am I just a little stupid and did I miss something?

Also, this comment suggests that it won't save state for the modified component, only states of other components, is that what is happening?

Thanks for your help!

I couldn't get it working either. I think the issue is the angular cli wiki instructions don't mesh with the instructions in this repo.

  • Angular cli wiki does not make use of hmrModule so functions like hmrOnInit are never called. This means we can't hook into things like saving ngrx state.
  • Adding hmrModule calls the hook functions successfully. But I couldn't figure out how to configure it. I always get "The ng module AppModule has already been destroyed." when trying to use it.

Actually I got it working. Just ignore the angular cli instructions. The only thing to take from that is using an environment to enable/disable hmr. Here's the relevant lines from my main.ts

const bootstrap = () => platformBrowserDynamic().bootstrapModule(AppModule);

if (environment.hmr) {
  if (module[ 'hot' ]) {
    bootstrap().then((ngModuleRef) => {
      return hmrModule(ngModuleRef, module);
    }).catch(err => console.log(err));
  } 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));
}

Otherwise follow the instructions in this repo's readme. This is tested with angular 7 - so this ticket could probably be closed. Perhaps a section on using with angular cli could be added that warns against using angular-cli's documentation.

Thank you!

After tinkering a bit with your suggestion, I got it working too.
Here are my app.module.ts and main.ts if anyone's interested:


main.ts

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

import { hmrModule } from '@angularclass/hmr';

if (environment.production) {
  enableProdMode();
}

const bootstrap = () => platformBrowserDynamic().bootstrapModule(AppModule);

if (environment.hmr) {
  if (module[ 'hot' ]) {
    // hmrBootstrap(module, bootstrap);
    bootstrap().then((ngModuleRef) => {
      return hmrModule(ngModuleRef, module);
    }).catch(err => console.log(err));
  } 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));
}

app.module.ts

import { removeNgStyles, createNewHosts, createInputTransfer } from '@angularclass/hmr';
import { NgModule, ApplicationRef } from "@angular/core";
import { AppComponent } from "./app.component";
...

@NgModule({
  declarations: [
    AppComponent,
    ...
  ],
  imports: [
    ...
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {
  constructor(public appRef: ApplicationRef) {}
  hmrOnInit(store) {
    if (!store || !store.state) return;
    // console.log('HMR store', store);
    // console.log('store.state.data:', store.state.data)
    // inject AppStore here and update it
    // this.AppStore.update(store.state)
    if ('restoreInputValues' in store) {
      store.restoreInputValues();
    }
    // change detection
    this.appRef.tick();
    delete store.state;
    delete store.restoreInputValues;
  }
  hmrOnDestroy(store) {
    var cmpLocation = this.appRef.components.map(cmp => cmp.location.nativeElement);
    // recreate elements
    store.disposeOldHosts = createNewHosts(cmpLocation)
    // inject your AppStore and grab state then set it on store
    // var appState = this.AppStore.get()
    store.state = {data: 'yolo'};
    // store.state = Object.assign({}, appState)
    // save input values
    store.restoreInputValues  = createInputTransfer();
    // remove styles
    removeNgStyles();
  }
  hmrAfterDestroy(store) {
    // display new elements
    store.disposeOldHosts()
    delete store.disposeOldHosts;
    // anything you need done the component is removed
  }
}

And I agree, a clearer documentation would be nice.

I'm also having issues with this. Tried your code @Epono, but it does not work for me. I can see clearly in the console the logs stating the changes, but no changes are being done in the browser.

image

Besides, when I start my app, I can see a strange error:

image

I got my main.ts and my app.module.ts exactly as yours. Any idea or clue I may have passed?

Thanks in advance.

Never encountered this error :/

Did you follow these instructions as well? Adding an environment and updating angular.json

Also, I run my projet with this command ng serve --configuration hmr, I'm not sure what yours does (I'm really no expert in Angular)

I created a small repo with a project in which HMR works for Angular 7.
Clone it, npm i and ng serve --configuration hmr, put some text in the input fields, change something in the code and you should see the changes while keeping what you put in the fields.

I created a small repo with a project in which HMR works for Angular 7.
Clone it, npm i and ng serve --configuration hmr, put some text in the input fields, change something in the code and you should see the changes while keeping what you put in the fields.

I tried it out but it doesn't work for me.

That's weird, I just tried it again with Angular 7.1.2 and it worked.
What's your problem exactly?

@beelio i tried it and it works for me too
what did you try exactly? maybe a fork we can look at?