Angular 2+ Application pre loader with percentage indicator
Asked Answered
M

6

12

Does anyone know the good solution for implementing Angular 2+ pre loader with percentage indicator ( Similar to Gmail's loading screen )?

I know that usual way is to add <div> inside our <app-root> and style it, maybe even add CSS animations and it will be replaced by app content once app is loaded.

But... What I am actually looking is to display animated splash screen ( SVG or whatever else ) where after animation completes loading bar should appear and show progress status.

enter image description here

At first point I was thinking about separate splash component that will be only component eagerly loaded and from there load all other modules but if I map that component to '/' how to display it on any other route as a first ( starting point ). Also, this means that Angular main bundle must be already loaded so this is not a good option.

Most likely this question is too broad and not suitable for Stack Overflow but I can't find anywhere a good solution for this. :(

Is there a way to load plain JavaScript without Angular that will load Angular and display progress? Or any other ( better ) idea?

This must be achievable since whole Gmail is Angular app and they have it :D

Miserable answered 19/6, 2018 at 2:28 Comment(0)
S
8

You may try ngx-progressbar, it is really cool. The API is not trivial but well documented, so you may build the progress bar of any complexity.


UPD After discussion I would suggest following approach (index.html)

1) Provide progress bar on the html level:

<my-app>
  <div style="width: 100%; background-color: grey;">
    <div id="myProgressBar" style="width: 1%; height: 30px; background-color: green;">
    </div>
  </div>
</my-app>

2) Load your app bundle and inject it into DOM manually via XMLHttpRequest

const tag = document.createElement('script');
const xhr = new XMLHttpRequest();
xhr.open('GET', 'my-angular-app-bundle.js?' + new Date().getTime());
xhr.onloadend = (e) => document.head.appendChild(tag);
xhr.send(); 

3) Use XMLHttpRequest.onprogress to watch the progress and to update progress bar params

const barElement = document.getElementById('myProgressBar');
xhr.onprogress = (e) => {
  if (e.lengthComputable) {
    const width = 100 * e.loaded / + e.total;
    barElement.style.width = width + '%';
  }
}

To make onprogress updates smoother you may increment progress bar width in a setInterval loop:

if (e.lengthComputable) {
  const endWidth = 100 * e.loaded / + e.total;
  const intervalId = setInterval(() => {
    const width = parseInt(barElement.style.width, 10);
    if (width >= endWidth) {
      clearInterval(intervalId);
    } else {
      width += 2; 
      barElement.style.width = width + '%'; 
    }
  }, 40);
}
Somersault answered 19/6, 2018 at 2:41 Comment(10)
It's really cool but I still need Angular to be loaded in order to use it. It's nice if I am displaying that for loading lazy loaded modules in app.Miserable
What I am thinking is to load whole app ( AOT compiled ) without lazy loading but to display progress before Angular is loaded. After Angular is loaded all modules will be there. Check Gmail to see how it should be.Miserable
@MilosMiskoneSretin I drafted a little demo, could you try it? stackblitz.com/edit/angular-ygfgju Does it look like something you need? All magic is in index.html.Somersault
It's more like a workaround :( This does not display real loading progress. I need to calculate Angular bundle size and display real percentage :(Miserable
I am now thinking to bootstrap only SplashScreen component and use it as entry component which will trigger loading of other modules and display loading progress but still don't know how to do it right :(Miserable
@MilosMiskoneSretin Hey! I updated the answer with the approach that, I think, is pretty close to what you needSomersault
Nice approach. Thanks, let me check if this can fit in totally before approving the answer.Miserable
It does some pretty good aproach, but still, with slow connections the bar will get 100% before actually loading all the appOke
@NeryOrtez You are absolutely right, I updated the answer, now setInterval is being used only for regular width changing each time the onprogress handler is being called.Somersault
in step 2), how does whatever the request returns land inside the created script tag ?Show
M
3

I have used PACE in my angular app to show the progress bar for the splash screen. You can also show as you want. You need to go through with below link:

Automatic page load progress bar

Hope it will help you.

Moslemism answered 11/7, 2018 at 5:7 Comment(0)
M
2

Sometimes tag-based loading is more efficient, you could use PreloadJS library. You could also manually track end of script loading using onload event and artificially interpolate progress to make impression that app is loading at constant speed. Gmail probably does not show actual progress at all, it just waits end of loading displaying fake steady progress using timers.

Maxantia answered 5/7, 2018 at 15:29 Comment(2)
I tested with different connection speed and Gmail seems to use real percentage. Also, if I use PreloadJS, do you have suggestion to implement it with AngularCLI since CLI on compile time adds JS bundle links automatically and here I'll need to load them manually?Miserable
cli allows embedding global scripts (i.e. PreloadJS), but i could not find any way to override app script tags generation, probably you have to write custom script and run it after ng build i.e. in scripts section of package.json.Maxantia
A
2

I don't think that loading indicator shows the loading of the app. I think it shows the loading of the data after the app has loaded. Think of data like mails, contacts, etc... I think that gmail loading is split in two parts.

Part 1: Show a simple animation (without loading indicator) while that app itself starts.

Part 2: Now the app has started keep displaying that loading annimation. Next, inventorise how many data requests you need to make and add a loading bar for this.

You can use this for the startup annimation.

Aztec answered 7/7, 2018 at 21:21 Comment(0)
A
1


maybe my answer is a little late, but you can check this tutorial, i think it's very realistic and useful implementation:

Implementing Simble PRogress Bar Angular/Server side

Appear answered 26/1, 2021 at 11:20 Comment(0)
L
0

The only way I think of is connecting your app to the CLI and display the progress it shows from the command line itself.

Leak answered 12/7, 2018 at 13:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.