Universal: When performing the first hit on server, client re-runs everything

Created on 9 Aug 2016  路  7Comments  路  Source: angular/universal

Note: for support questions, please use one of these channels: https://github.com/angular/universal/blob/master/CONTRIBUTING.md#question. This repository's issues are reserved for feature requests and bug reports.

  • I'm submitting a ...
  • [x] bug report
  • [ ] feature request
  • [ ] support request => Please do not submit support request here, see note at the top of this template.
  • What modules are related to this pull-request
  • [ ] express-engine
  • [ ] grunt-prerender
  • [ ] gulp-prerender
  • [ ] hapi-engine
  • [ ] universal-preview
  • [x] universal
  • [ ] webpack-prerender
  • Do you want to request a _feature_ or report a _bug_?
    report a _bug_ or request a _feature_
  • What is the current behavior?
    When I perform the first hit on the server, the server runs the app, renders the html and delivers it to the client. The problem is that the client re-runs the app, instead keeping the app state that was downloaded from the server. This way, the user experiences a flicker/blink of the page.
  • 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.
  • What is the expected behavior?
    When the client accesses the app for the very first time, the browser should keep the state of the result returned by the server, instead of running everything again. Also, there should be provided a strategy to choose which part of the app can be re-runed at the client side (when it is the first hit on the app). For instance, an online store could run the home component at the server, and the client could do what is particular to the user (an http request to get its cart, for example).
  • What is the motivation / use case for changing the behavior?
    Having a strategy to decide the behavior of the app in different scenarios would give to developers and users a powerful experience. We could decide to run always on server, always partially on server and client or always on client.
  • Please tell us about your environment:
  • Angular version: 2.0.0-RC4
  • Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX ]
  • Language: [all | TypeScript 1.8 | ES6/7 | ES5 ]
  • OS: [all | Mac OS X | Windows | Linux ]
  • Platform: [all | NodeJs | Java | PHP | .Net | Ruby]
  • Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, gitter, etc)

Most helpful comment

@felipedrumond So, three important things to know here.

First, as @MarkPieszak pointed out, there is a separate issue for transferring state from server to client. This, however, will never solve every use case and you will need to re-pull data in various scenarios (ex. if you have client-only rendered components that need certain data).

Second is that even with the current setup and without the automatic state transfer, we can help you get rid of the flicker. The flicker is due to a bug in an older version of preboot. So, forgetting about the client re-running everything (that doesn't matter...what matters is the flicker), the fix is using the most recent version of preboot. This is _almost_ completely integrated into universal core. We should be publishing a new version of universal in the next couple days which uses the latest preboot which SHOULD solve the flicker issue. If it doesn't for whatever reason, please post something here or on the preboot repo https://github.com/angular/preboot.

Last thing to be aware of is that we have discussed hydrating the client on top of the server view so even less client side logic has to be run. However, as it looks right now, if we solve the flicker issue with the latest preboot and easily allow for state transfer, the fact that rendering logic runs multiple times shouldn't make any difference. If it does, we will explore hydration more but right now it is likely not worth the effort.

All 7 comments

There is an open issue talking about how we can achieve a Store for exchange between server and client for at least storage / xhr calls here https://github.com/angular/universal/issues/489
Is that what you're referring to?

Besides that, everything else has to be rendered again, since the client has to bootstrap itself.

@felipedrumond So, three important things to know here.

First, as @MarkPieszak pointed out, there is a separate issue for transferring state from server to client. This, however, will never solve every use case and you will need to re-pull data in various scenarios (ex. if you have client-only rendered components that need certain data).

Second is that even with the current setup and without the automatic state transfer, we can help you get rid of the flicker. The flicker is due to a bug in an older version of preboot. So, forgetting about the client re-running everything (that doesn't matter...what matters is the flicker), the fix is using the most recent version of preboot. This is _almost_ completely integrated into universal core. We should be publishing a new version of universal in the next couple days which uses the latest preboot which SHOULD solve the flicker issue. If it doesn't for whatever reason, please post something here or on the preboot repo https://github.com/angular/preboot.

Last thing to be aware of is that we have discussed hydrating the client on top of the server view so even less client side logic has to be run. However, as it looks right now, if we solve the flicker issue with the latest preboot and easily allow for state transfer, the fact that rendering logic runs multiple times shouldn't make any difference. If it does, we will explore hydration more but right now it is likely not worth the effort.

Nice! I've been considering using A2 and Universal for a project I will start working on soon and was worried that the flickering-issue would put a stop to those plans, so this fix is great news for me. Looking forward to try the new version.

Hi @jeffwhelpley, thank you for your extensive reply! We managed to solve the flicker just by configuring the preboot to use buffer and forcing our client to call prebootComplete event after a zero-seconds timeout.

@Honn, if you see the flicker, try configuring your application with the code below.

main.node.ts

preboot: { appRoot: 'app', buffer: true }

client.ts

document.addEventListener('DOMContentLoaded', () => {

  ngApp()
      .then(() => {
          setTimeout(prebootComplete, 0);
      });

});

I'm back with a new simular issue :-(
After migrating angular RC4 to final release and creating loads of modules for my application, my application now has a strange behaviour: it blinks only the content of router-outlet.

My app.component.html has the following html structure:
<header></header> <router-outlet></router-outlet> <footer></footer>

This way, my app constructs header (which has some requests to an web api) and footer (which has static html) only once.

If I open my app at _localhost:3000/company_, the app will lazy load my company.module and displays its content. My company.component has static html.

After requesting _localhost:3000/company_, node server renders the entire page (header+company+footer). The browser correctly displays it (great!), but when the app is started at the client, the content of router-outlet disappears and then reappears. Header and footer stay unchanged.

I was wondering... is the router resolving the route again?

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings

Related issues

leon picture leon  路  4Comments

benrondeau picture benrondeau  路  5Comments

ahmedwerpx picture ahmedwerpx  路  4Comments

matthewharwood picture matthewharwood  路  4Comments

moczix picture moczix  路  5Comments