Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FOUC creates unreliable JS style calculations on page load #293

Closed
t-kelly opened this issue Jan 12, 2018 · 3 comments
Closed

FOUC creates unreliable JS style calculations on page load #293

t-kelly opened this issue Jan 12, 2018 · 3 comments

Comments

@t-kelly
Copy link

t-kelly commented Jan 12, 2018

FOUC in a development environment isn't really a problem
@michael-ciniawsky in #221 (comment)

Related

Style-loader uses a <link> to include styles when sourcemaps are enabled. Since injecting a <link> tag into the page via JS, after page-load, results in the the stylesheet being downloaded asynchronously, other JS has time to execute before that stylesheet is downloaded and applied to the page.

The resulting FOUC causes problems when JS needs to read styles from the DOM and is expecting a fully styled page. For example, let's say you have the following page built for production, that uses HTMLWebpackPlugin to inline a <link> tag at build-time.

styles.css

header {
  height: 100px
}

index.html

<html>
<head>
  ...
  <link rel="stylesheet" href="/styles.css">
</head>
<body>
  <header id="header"> My header </header>
  ...
  <script>
    console.log(document.getElementById("header").styles.height);
  </script>
</body>

The height logged will always be 100px because a <link> tag that is included on page load is synchronous and render-blocking.

The same page when using style-loader with source-maps will always end up with another value (the unstyled page value) because the JS executes before the stylesheet has loaded.

The unreliability produces big problems for features like sticky elements in development, which need access to the styled page values to function correctly.

This problem is identical to those encountered when working with asynchronous stylesheets, e.g. using a lib like LoadCSS. One solution would be to check if the stylesheet has loaded before executing the JS, but that kind of sucks since this problem only exists in dev.

@michael-ciniawsky
Copy link
Member

michael-ciniawsky commented Jan 13, 2018

v1.0.0 of style-loader will always use inline maps instead of a <link> tag (which should mitigate this a bit), but if the project exceeds a certain size and the style-loader needs to add a lot of <style> tags, it's likely to result in FOUC aswell at some point. I really don't know what else can be done here from our side to avoid FOUC altogether or to mitigate this further. As you already mentioned it's possible to add an event listener before checking anything style related and/or to 'simply' disable CSS source maps when testing 'more advanced' style integrations. I intend to tinker around with splitting source maps from the <style id="1">...css</style> (head) and insert them in the body via a separate <style data-id="${id}">...map</style> instead. No idea if this actually avoids FOUC or brings any performance benefits. Browser support for this is also a concern...

<head>
   <style id="1">CSS</style>
</head>
<body>
    <div id="app"></div>

     
    <style data-id="1">SourceMap</style>
</body>

Any other suggestions are highly welcome :)

@t-kelly
Copy link
Author

t-kelly commented Jan 17, 2018

What if style-loader and HMR worked in tandem with ExtractTextPlugin?

You could use the ExtractTextPlugin to inline a <link> tag in the HTML for initial page load -- that way it loads synchronously. Then let HMR take over for business as usual?

@michael-ciniawsky
Copy link
Member

We are reworking the CSS Pipeline in general, webpack may even get 'native' CSS support out-of-the-box in the near future, which makes things you mentioned possible. I'm closing this issue here, since there is nothing we can really do in the scope of style-loader atm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants