Skip to content

HMR: app.module bootstrapped multiple times #1954

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
lambourn opened this issue Aug 20, 2019 · 5 comments
Open

HMR: app.module bootstrapped multiple times #1954

lambourn opened this issue Aug 20, 2019 · 5 comments

Comments

@lambourn
Copy link

Environment
Provide version numbers for the following components (information can be retrieved by running tns info in your project folder or by inspecting the package.json of the project):

  • CLI: 5.3
  • Cross-platform modules: 5.3.2
  • Android Runtime: 5.3
  • NativeScript-Angular: 7.2.3
  • Angular: 7.2.9

Describe the bug
When using HMR, our Angular-based application gets bootstrapped multipled times. More precisely: the app.module gets bootrapped multiple times in a single HMR run. Looks like a recursion while processing the modules.

I try to reproduce the issue but having diffculties to get to the root cause.

The only thing I can see is that this behaviour starts as soon as code in a @Injectable which is provided by the main app.module is changed or if the @Injectable is in the dependency chain of affected modules.

The multiple bootstrapping does not happen if code in a UI/view is changed, e.g. a regular @component.

Example #1 - code change in @component. Works as expected. Resulting log:

HMR: Checking for updates to the bundle with hmr hash 7dac85d1bc298888736a.
HMR: The following modules were updated:
HMR:    ./something/some.component.ts
HMR:    ./something/some.module.ts
HMR:    ./something/some.routing.ts
HMR: Successfully applied update with hmr hash 7dac85d1bc298888736a. App is up to date.
JS: bootstrap: Angular livesync started.
JS: AppModule constructor  <-- as expected 
JS: bootstrap: Angular livesync done.

Example #2 - code change in @Injectable. Resulting log:

JS: HMR: Checking for updates to the bundle with hmr hash 0903a733694101ec7f8a.
JS: HMR: The following modules were updated:
JS: HMR:          ↻ ./service/whatever.service.ts
JS: HMR:          ↻ ./app.component.ts
JS: HMR:          ↻ ./app.module.ts
JS: HMR:          ↻ ./components/another.component.ts
JS: HMR: Successfully applied update with hmr hash 0903a733694101ec7f8a. App is up to date.
JS: bootstrap: Angular livesync started.
JS: AppModule constructor                    <-- as expected
JS: bootstrap: Angular livesync done.
JS: bootstrap: Angular livesync started. <-- 2nd run... why?
JS: AppModule constructor                     <-- 2nd bootstrapped AppModule
JS: bootstrap: Angular livesync done.

Following HMR updates/reloads cause even more bootstraps.

What could be the reason for this? Or is this even expected behaviour?

@NL33
Copy link

NL33 commented Oct 2, 2019

Bump. I am having a similar issue. My app gets bootstrapped according to the number of times Hot Module Replacement has run.

So running it the first time, it is bootstrapped once. Then, if I make a change to the app, the app will then get bootstrapped twice. Make another change, the app will get bootstrapped 3 times.

Using NS angular, 5.3.1.

Any ideas for fixing this?

@AnthonyLenglet
Copy link

This issue is still present in the latest release, has there been any news regarding this issue ?

@edusperoni
Copy link
Collaborator

This behavior is intended with HMR. This also happens on the web:

https://stackblitz.com/edit/angular-hotreload-lifecycle?file=src/app/app.component.ts

Things to note:

  1. I've changed how stackblitz hot reload works (check main.ts) to reflect exactly how NS does it.
  2. you can change it back (flip simulateNativescript to false), will only change the order of contruction/destruction (will destroy instance 2 AFTER constructing instance 1)

Check the console.log and see the AppModule construct happens many times (uncheck clear console on reload if you want the full log, as hot reloads count as a "reload").

When running with ng serve you're not using HMR, the whole page is being refreshed (this is like closing and opening the app, but keeping the history stack). See https://levelup.gitconnected.com/hmr-in-angular-cli-project-eb8512ef514b for how you'd configure HMR on a normal angular project.

I'd also like to add that multiple constructs is intended on normal usage too. When you exit the app via back button, the rest of the application is still running (timers, native stuff, etc), but angular is destroyed (there is no frontend to show anymore) so ensure you're clearing up your subscriptions and timers on ngOnDestroy (all modules/components/services/directives/etc can implement this lifecycle hook).

@plackowski
Copy link

I'm not sure if my app has a problem with HMR, but I can't figure out since many weeks why my app is working as I described it here: https://stackoverflow.com/questions/61253807/possible-memory-leak-in-nativescript-app-if-user-reopens-his-app-multiple-times

@edusperoni, do you think, it can be related to this topic about HMR?

The problem is that when I'm moving my app to the background of my mobile device and then open that app again (for example a few times). Then, when I logout the user subscription emits as many times as I moved the app to the background and back before. So if I move app to the background and open that app 5 times, then if I logout my user, then this.authenticationService.user$ emits 5 console.logs. I use async and try to use ngOnDestroy everywhere, but without success :/

@yozian
Copy link

yozian commented Sep 10, 2020

The same problem faced. 😭 The HMR causes all the components and services(singleton provide in root) initialize twice.
Is there any solution to avoid that?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants