html briefly displayed when page is loading

3.4k views Asked by At

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?

5

There are 5 answers

0
Robin Dijkhof On

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

2
Hendrik Brummermann On

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.

0
Maciej Treder On

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.

0
Jan Kyu Peblik On

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.

0
LSerni On

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).