skip to Main Content

I have several sites built in Angular 7 with SSR for SEO improvements. All apps themselves are fine however it always happens that either the very first time or when you perform a hard refresh there is this small blip whereby all content is shown and suddenly the site itself “reloads”.

All conditions for ngIf‘s that may hide components that are evaluated in the ngOnInit section of the components seem to be ignored and animations that may start with opacity = 0 to hide HTML elements are also shown.

That said I read a lot regarding this in different forums, posts, github issues etc however I haven’t been able to get to any solution.

I tried changing the main.ts to have:

document.addEventListener('DOMContentLoaded', () => {
    platformBrowserDynamic().bootstrapModule(AppModule);
});

instead of the classic bootstrap mechanism for no joy. I have tried the option for the initialNavigation enabled in the AppRouting but still doesn’t work:

@NgModule({
    exports: [ RouterModule ],
    imports: [ RouterModule.forRoot(routes, {enableTracing, scrollPositionRestoration: 'enabled', initialNavigation: 'enabled'}) ],
})
export class AppRoutingModule {}

I read through the issue here which I thought it may be related:
https://github.com/angular/angular-cli/issues/7477 but it ends referring to the initialNavigation flag which hasn’t worked for me.

I’m not sure if there is anything else that I could try here or anything “special” to be set up but it would be really nice to have no delay or hide the actual rendered page which is causing the navigation to be a bit less friendly.

Note that this is JUST on the first load, first time load or hard refresh. The rest of the navigation is absolutely fine.

2

Answers


  1. Actually the flicker occurs because the server side of your app is first loaded by the browser and the client then subsequently loaded. Therefore, a quick workaround I implemented was to add a “display: none” on the landing page for the server side only.

    To implement, wrap your main component in a tag and add a conditional display clause to it. I will suggest you do this only on your landing page. Using bootstrap 4, this is what your the main layout should look like:

    app.layout.html

    <div  [className]="!display?'d-none':''">
        <app-navbar current_page="post"></app-navbar>
        <router-outlet ></router-outlet>
        <app-footer></app-footer>
    </div>
    

    Take note of the [className]=”!display?’d-none’:””

    and in the component.ts file:

    app.component.ts

    import {Component, Inject, OnInit, PLATFORM_ID} from '@angular/core';
    import {isPlatformBrowser} from '@angular/common';
    
    @Component({
      selector: 'app-layout',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.scss']
    })
    export class AppComponent implements OnInit {
      display = true;
      constructor( @Inject(PLATFORM_ID) private platformId: Object) {
        if (!isPlatformBrowser(this.platformId)) {
          this.display = false;
        }
      }
    
      ngOnInit() {
      }
      onActivate(event) {
    
      }
    }
    
    

    Like I mentioned, its a workaround that actually works.

    Login or Signup to reply.
  2. I had the same issue and my solution was to enable ssr only for crawlers (google, yahoo, facebook…).

    // server.ts
    // All regular routes use the Universal engine
    server.get('*', (req, res) => {
      // serve ssr only to web crawlers
      if((/(google|bing|yahoo|slurp|facebot|duckduck)/gi).test(req.headers['user-agent'])){
          res.render(indexHtml, {
            req,
            providers: [{provide: APP_BASE_HREF, useValue: req.baseUrl}]
        });
      }
      else{
        res.sendFile(join(distFolder, 'index.html'));
      }
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search