angular/preboot

Preboot buffer: Application bootstrap on the server generated node.

Willovent opened this issue ยท 6 comments

  • I'm submitting a ...
  • bug report
  • feature request
  • Which parts of preboot are affected by this issue?
  • server side
  • client side
  • inline
  • build process
  • docs
  • tests
  • What is the current behavior?
    Sometime the application bootstrap on server generated DOM node, leaving the hidden buffer empty.
    When this happened, once the app is stable, preboot will delete the node containing the booted application and leave the empty buffer node.

  • If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem by creating a github repo.
    So here is the code causing the issue:

  • app.module.ts

const eventSelectors: any[] = [
  { selector: 'input,textarea', events: ['keypress', 'keyup', 'keydown', 'input', 'change'] },
  { selector: 'select,option', events: ['change'] },
  { selector: 'input', events: ['keyup'], preventDefault: true, keyCodes: [13], freeze: true },
  { selector: 'form', events: ['submit'], preventDefault: true, freeze: true },
  { selector: 'input,textarea', events: ['focusin', 'focusout', 'mousedown', 'mouseup'], replay: false },
  { selector: 'button,hg-event-bet-type-item', events: ['click'], preventDefault: true, freeze: true }
];
@NgModule({
  imports: [
    AppRoutingModule,
    BrowserTransferStateModule,
    HttpClientModule,
    BrowserModule,
    ServerTransition.forRoot({ appId: 'hg-customer' }),
    PrebootModule.withConfig({ appRoot: 'hg-root', replay: false, eventSelectors }),
  ],
  declarations: [ ],
  providers: [{ provide: HTTP_INTERCEPTORS, useClass: TransferHttpCacheInterceptor, multi: true }]
})
export class AppModule { }
  • app.server.module.ts
@NgModule({
  imports: [ServerModule, AppModule, ServerTransferStateModule],
  bootstrap: [AppComponent]
})
export class AppServerModule {}
  • app.browser.module.ts
@NgModule({
  imports: [AppModule],
  bootstrap: [AppComponent]
})
export class AppBrowserModule {  }
  • app.component.ts
@Component({
  selector: 'hg-root',
  template: `<router-outlet></router-outlet>`
})
export class AppComponent {
  constructor(
    @Inject(PLATFORM_ID) private platformId: string,
    private eventReplayer: EventReplayer,
    private appRef: ApplicationRef
  ) {
    if (isPlatformBrowser(this.platformId)) {
      this.appRef.isStable.pipe(filter((isStable: boolean) => isStable), take(1))
        .toPromise()
        .then(() => {
          if (!document.querySelector('hg-root').innerHTML.length) {
            debugger;
            console.log(document.body.innerHTML);
          }
          this.eventReplayer.replayAll();
        });
    }
  }
}
  • body part of index.html:
<body>
  <hg-root>Loading...</hg-root>
</body>
  • What is the expected behavior?
    The application should boot everytime in the buffer DOM node

  • Please tell us about your environment:

  • Browser: Chrome 67
  • Language: TypeScript 2.7.1
  • OS: Windows
  • Platform: Nodejs
  • Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, gitter, etc)
    As you can see in the file app.component.ts, I trigger a debugger; when the buffer is empty while the app is stable. When this is the case, the DOM look like this:
    booted
    Once the replayAll() is done, it's only leaving the empty hg-root node in the DOM.
    To be sur that the app was boostrapping in the wrong node, I changed some string the client main.js file. Those string were changed in the second hg-root DOM node, proving the application is well booted but in the wrong node.

After futher search, it appear that the bootstrap of the application is started before preboot can create the buffer node. The bootstrap was done in the event DOMContentLoaded, for now I had a setTimeout(10) to go with the waitUntilReady preboot function and it seems to be ok.

mgol commented

If I'm reading it right it might be fixed by PR #83 as it removes waitUntilReady and invokes relevant code immediately, before the Angular JS has a chance to even start loading - so definitely before it bootstraps.

Yes totally. Thanks for the hard work on that PR !

Any ETA on a release for this fix?

@rezonant Just published, let me know if there are any bad effects.

@CaerusKaru I don't see any bad effects for now and this issue is resolved with the new version. Thanks a lot.

mgol commented

@Willovent in that case could you close the issue?