See Start your pushes before you respond.
Indeed we can fix the problem by pushing before the HTML is sent, however that increases TTFB by a lot and creates a completely new set of performance problems. Therefore we're pushing resources after sending the HTML. When we do that, there are 2 possible async flows that can occur.
- Server sends HTML.
- Server pushes CSS/JS.
- Client receives HTML.
- Client receives information about the push.
- Client parses HTML and notices CSS link reference.
- Client knew about the push, hence loads CSS from push without sending an additional request.
- Server sends HTML.
- Server pushes CSS/JS.
- Client receives HTML.
- Client parses HTML and notices CSS link reference.
- Client doesn't know about the push yet, therefore sends a request for the stylesheets to the server.
- Client receives information about the push but it's already too late.
In most of my tests using the Chrome browser (as the other browsers lack tools to show if a resource has been loaded from push), the worst case scenario has only happened a few times. However, I was wondering if there is any standardized way to prevent it.
Update, March 2018: In recent Chrome versions (64+), this synchronization issue seems to be more frequent.