3

In my Angular app, my menu component html code is displayed briefly when the page is loading. Even if I hide the menu html root element with a display none css, the html is still displayed when the page start loading. I have read a lot of thing about ng-cloak (https://docs.angularjs.org/api/ng/directive/ngCloak) but it seems Angular 4 not have ngCloak.

So I don't know how to prevent this unpleasant effect.

does Angular 4 have an equivalent directive for ng-cloak? How can I display properly page without display unstyled html on load?

Maciej Treder
  • 11,866
  • 5
  • 51
  • 74
soung
  • 1,411
  • 16
  • 33

5 Answers5

6

The index.html file should not contain any application specific HTML code. But just some headers and the root tag of the application. It may contain a placeholder text like "Loading" inside the root tags.

All the html code of the application should be inside the app.component.html and or other components.

@angular/cli generates an index.html "template" file that looks like this:

<!doctype html>
<html>
    <head>
        ...
    </head>
    <body>
       <app-root>Loading...</app-root>
    </body>
</html>

The browser immediately displays the "Loading..." text. After Angular was initialized, it is replaced with the actual application. To get a white page, just removed the text.

Hendrik Brummermann
  • 8,242
  • 3
  • 31
  • 55
  • 2
    Hi Hendrik. My index.html dosn't contain any specific html code. it containe just the app-root tag wich component include the header. So Loading ... is displayed. Just after the unstyled html of the header is displayed. thats the problem. – soung Aug 13 '17 at 21:30
  • Is that `Loading...` placeholder only works for ``? Or for any angular component that are slowly rendered? – starfruit3254 Feb 21 '22 at 12:53
2

I would have gone with @HendrikBrummermann's answer: place a "Loading..." tag.

From your comment, "...which component includes the header... the unstyled html of the header is displayed", I believe you already have your answer: there is no CSS loaded that can style the HTML of the header yet.

Hendrik's answer keeps the tag to a minimum, so this effect is not apparent.

If you really need to style the header immediately, I fear that you need to use an inline style (and with no images or fonts - those won't be loaded yet either). Keep that to the bare minimum is all:

<!doctype html>
<html>
    <head>
        ...
        <style>
        ...
        </style>
    </head>
    <body>
       <app-root>(styled header)</app-root>
    </body>
</html>

Then upon loading you can remove the placeholder.

You can also try (but it's messy and difficult to maintain) an incremental approach with two "loaders": a very, very minimal one that needs next to no CSS/images, then as soon as the fonts and other very few basic assets are onLoad'ed you can maybe replace it with a simple animation, and from there you load all the rest and activate the full Angular app.

There are also "packager" utilities that will compact most of your HTML, CSS and JS into a single minified SPA bundle; some of them (I'm sorry, I saw a couple of them used, but never used myself and can't reference them) also supply a minimal loader as described above. This might take care of some maintenance for you, and it's perhaps worth a shot. I know this because for one project a colleague of mine had to replace a Flash "Please wait" loader with a HTML5 one (it wasn't an Angular project, but I don't think it matters).

LSerni
  • 55,617
  • 10
  • 65
  • 107
1

Those are things which you could give a try:

  1. (In my opinion best solution) You can use Angular Universal, for serverside rendering. Workflow is:

    • User sends request to example.com
    • Server is not responding with pure HTML (example above), but runs Angular on the server side and render output HTML
    • This HTML (together with <script> tag pointing to compiled app is send to users browser
    • On the first look, the user sees HTML + CSS formatted by his browser. Then browser launches *.js file, and after a while replace "static page" with "single page app"
    • Angular can deal with all action done on "static page" (before JavaScript launch), thanks to BrowserModule.withServerTransition(); More about Universal can be read here.
  2. You can make one step further from Universal, and serve your Angular Universal App as a Progressive Web App (PWA). More about PWA can be read here

  3. Go one more step further, and introduce Accelerated Mobile Page (AMP), from the Google Cache. More about AMP can be read here.

  4. You should never ever place anything more than application root node in your index.html:

<!doctype html>
<html>
  <head>
    ...
  </head>
  <body>
    <my-app>Loading...</my-app>
  </body>
</html>
  1. If you really want to have something "nice" while the user is waiting for Angular, you could create some kind of loader with ie css animation:

<!doctype html>
<html>
    <head>
        <link rel="stylesheet" href="loader.css">
    </head>
    <body>
       <app-root>
           <div id="css-loader"></div>
       </app-root>
    </body>
</html>

Regarding points 1 & 2 & 3: Here you can find an example of Angular Universal & PWA & AMP combined.

Maciej Treder
  • 11,866
  • 5
  • 51
  • 74
0

I think this behaviour is inevitable. Best you can do is speed it up as much as possible. Using the lastest versions, AOT and lazy-loading helps a lot.
Alternatively you can add some css to your index.html

Tschallacka
  • 27,901
  • 14
  • 88
  • 133
Robin Dijkhof
  • 18,665
  • 11
  • 65
  • 116
0

This is a feature, not a bug.

You can do one of twothree things:

  1. Let UAs get information as soon as they can and assume people can tell when things are loaded fully, or
  2. Make people wait for information, and show it to them only after it has all loaded
  3. Some kind of absurd gray area unicorn implementation that ensures part of the page is loaded before displaying it but doesn't bother for other parts

Historically, #2 has been the most derided approach, especially as so many people want to do it. I suggest not even pursuing it.

Jan Kyu Peblik
  • 1,435
  • 14
  • 20