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

[v2] Webpack V4 style-loader FOUC in development #6211

Closed
ooloth opened this issue Jun 28, 2018 · 41 comments
Closed

[v2] Webpack V4 style-loader FOUC in development #6211

ooloth opened this issue Jun 28, 2018 · 41 comments
Labels
help wanted Issue with a clear description that the community can help with. type: bug An issue or pull request relating to a bug in Gatsby

Comments

@ooloth
Copy link
Contributor

ooloth commented Jun 28, 2018

Description

Since #6008 and #6009, CSS styles are no longer inlined in development (they are still inlined in production). In development, this causes a flash of unstyled content followed by a layout jump when the styles are applied.

Steps to reproduce

Create a Gatsby v2 site using CSS (rather than CSS-in-JS). In development, the styles will be applied via a link tag (causing a flash of unstyled content). In production, the styles are inlined, leading to the same smooth loading experience as in v1.

Expected result

To prevent developer confusion, the visual behavior of a Gatsby site should be the same in development and production. The timing of loading and applying CSS styles affects this consistency. V1 achieved this consistency by always inlining styles.

Actual result

When using CSS, V2 offers an inconsistent experience in development vs. production by switching between inlining and not-inlining CSS styles.

(If I've misunderstood any of this, please let me know!)

Environment

  System:
    OS: macOS High Sierra 10.13.5
    CPU: x64 Intel(R) Core(TM) i5-7500 CPU @ 3.40GHz
    Shell: 5.3 - /bin/zsh
  Binaries:
    Node: 8.7.0 - /usr/local/bin/node
    Yarn: 1.5.1 - /usr/local/bin/yarn
    npm: 6.1.0 - /usr/local/bin/npm
  Browsers:
    Chrome: 67.0.3396.99
    Firefox: 60.0.2
    Safari: 11.1.1
  npmPackages:
    gatsby: next => 2.0.0-beta.9 
    gatsby-cli: next => 2.0.0-beta.2 
    gatsby-image: next => 2.0.0-beta.2 
    gatsby-plugin-favicon: ^2.1.1 => 2.1.1 
    gatsby-plugin-manifest: next => 2.0.2-beta.2 
    gatsby-plugin-netlify: next => 2.0.0-beta.2 
    gatsby-plugin-netlify-cache: ^0.1.0 => 0.1.0 
    gatsby-plugin-offline: next => 2.0.0-beta.2 
    gatsby-plugin-react-helmet: next => 3.0.0-beta.2 
    gatsby-plugin-robots-txt: ^1.0.2 => 1.0.2 
    gatsby-plugin-sharp: next => 2.0.0-beta.2 
    gatsby-plugin-sitemap: next => 2.0.0-beta.2 
    gatsby-plugin-webpack-bundle-analyzer: ^0.1.1 => 0.1.1 
    gatsby-source-filesystem: next => 2.0.1-beta.3 
    gatsby-transformer-sharp: next => 2.1.1-beta.2 
    gatsby-transformer-yaml: next => 2.1.1-beta.2 
  npmGlobalPackages:
    gatsby-cli: 2.0.0-beta.2
@m-allanson m-allanson added type: bug An issue or pull request relating to a bug in Gatsby help wanted Issue with a clear description that the community can help with. labels Jun 29, 2018
@m-allanson
Copy link
Contributor

Hmm I'm actually not sure how Gatsby decides whether to inline CSS or not. I agree that having the styles inlined for gatsby develop seems sensible.

@KyleAMathews
Copy link
Contributor

#6009 was just a change to production not development. Do you have a reproduction? I just ran the using-css-modules example and the styles loaded instantly.

@ooloth
Copy link
Contributor Author

ooloth commented Jul 1, 2018

Thanks for the replies! Gatsby is the best. :)

Thanks for clarifying about #6009. Nevertheless, I notice styles are no longer inlined in development in v2 (I guess this happened in a different PR). Was there a reason for changing this behavior?

Here is a repo reproducing the style loading issues: https://github.com/ooloth/gatsby-v2-css-test. The repo uses a single global CSS file (as I usually do), rather than CSS modules. I prefer a Tachyons/Tailwinds/PurgeCSS CSS approach as it gives me the fastest dev workflow.

In development, each time you refresh the demo site, you should see a FOUC followed by a big layout jump. This did not occur in v1.

In production, these issues disappear, so it seems like inlining CSS in development again is all that's needed.

@ooloth
Copy link
Contributor Author

ooloth commented Jul 1, 2018

In addition to the FOUC, there are some worse styling issues in development when using global CSS with v2 as well (e.g. certain styles sometimes not applying at all; plugins like react-headroom sometimes calculating their dimensions incorrectly, etc).

However, the FOUC is the easiest issue to demonstrate and may be enough to warrant the inline CSS fix on its own.

@KyleAMathews
Copy link
Contributor

Investigated the problem a bit. Found a few plugins which try to solve the issue:

Also this thread:

If someone would like to create a PR fixing this problem, that'd be great!

@jquense
Copy link
Contributor

jquense commented Jul 14, 2018

I'm a bit confused about what changed from v1, the dev flow doesn't use extract text right? All dev css is handled via style-loader which is the same as v1, and the flash of unstyled content with style-loader is a frustrating but multi-year long-standing issue with webpack.

I guess overall I'm just interested why it seems to be worse now?

@ooloth
Copy link
Contributor Author

ooloth commented Jul 15, 2018

@jquense. The issue actually didn't occur in Gatsby v1. The reason it happens in v2 seems to be that v2 loads CSS via a link tag in development (rather than inlining it), while v1 inlined CSS in both development and production.

I'm not sure why this change occurred in v2 (maybe a side effect of the move from extract-text-plugin to mini-css-extract-plugin for webpack v4?), but the lack of inlining in development seems to be the behavior change that created this issue in v2.

The docs contain the following code comment on the "Custom webpack config" page:

// We don't need to add the matching ExtractText plugin
// because gatsby already includes it and makes sure its only
// run at the appropriate stages, e.g. not in development 

The "e.g. not in development" part of that comment suggests an awareness that CSS is not being inlined in development in v2 (if I'm understanding it correctly). Unfortunately, this makes it difficult for those using traditional CSS to know which styling issues in development are bugs and which will disappear in production when inlining occurs.

Hope that helps!

@jquense
Copy link
Contributor

jquense commented Jul 15, 2018

I'm not sure what you mean by "inlined" in v1, here. the configuration for css for dev is exactly the same for v2 as v1. That flow is style-loader -> css-loader. How the styles are added in devlopement has always (as far as i can see) been handled directly by webpack. Css was only inlined in production in the default html gatsby provided in v1.

@jquense
Copy link
Contributor

jquense commented Jul 15, 2018

btw i'm not trying to discount the issue here, just understand it!

@ooloth
Copy link
Contributor Author

ooloth commented Jul 15, 2018

Thanks for diving in, @jquense!

I totally understand that the webpack treatment of CSS doesn't appear to have changed. The reason for the new behavior is a mystery to me as well and doesn't appear to have been intentional.

Css was only inlined in production in the default html gatsby provided in v1.

In my experience building a half dozen Gatsby v1 sites, CSS was always inlined in development (by "inlined", I mean the CSS was output within a style tag, rather than linked to externally via a link tag).

Here is how CSS is loaded in development on a Gatsby v1 site I recently launched (notice the style tag):
gatsby v1 in development

Here is how CSS is loaded in development on a Gatsby v2 site I'm working on (notice the link tag):
gatsby v2 in development

Thanks!

@KyleAMathews
Copy link
Contributor

The link tag in v2 is the same thing as it's a base64 blob. The question is why did the styles get added before the initial render in v1 and after in v2.

@ooloth
Copy link
Contributor Author

ooloth commented Jul 15, 2018

Thanks for clarifying!

@jquense
Copy link
Contributor

jquense commented Jul 15, 2018

yeah sorry, i should have been clearer. webpack does inline them, what i meant was the explicit inlining of compiled styles that gatsby was doing, which was not happening in v1. Sorry for the confusion

yes the data:uri should be equivilent. I totally get the FOUC is happening and i'm certain it's webpack's fault. it happens on most webpack sites i've made during dev. I'm just interested why it's suddenly getting worse, or more apparent here. I think the base problem is that styles are loaded/inserted via JS when the code loads vs built ahead of time and loaded in the head. Yes webpack inline's them but it does it programatically, at runtime. not when the html file is built.

The reason this may be more apparent now might be css source maps which i don't think were working correctly in v1.

webpack-contrib/css-loader#613 (comment)
facebook/create-react-app#591 (comment)
webpack-contrib/style-loader#221 (comment)

@octalmage
Copy link
Contributor

octalmage commented Jul 16, 2018

I'm wondering if I'm dealing with this now on my site:

https://jason.stallin.gs

Just merged the Gatsby v2 branch and I'm seeing the flash. I'm digging into it now.

Edit: to be clear I'm only seeing the issue in production, not locally. It looks like the CSS just gets loaded after page load.

@KyleAMathews
Copy link
Contributor

@octalmage this issue is just about FOUC in development. If you see FOUC in production, it's generally an issue with site code.

@octalmage
Copy link
Contributor

Cool thanks! It seemed note worthy since it happened after migrating to Gatsby v2. Do you think it would be worth while to update a v2 doc somewhere once I find the root cause?

@KyleAMathews
Copy link
Contributor

@octalmage yeah! One you pinpoint the issue, if it's something that should be covered in the upgrade guide or doc, that'd be great to add.

@jlengstorf
Copy link
Contributor

This seems like an upstream issue, so I'm not sure if we can fix it inside Gatsby. Should we close this?

Another potential option appears to be using ExtractTextPlugin to circumvent style-loader altogether. I'm not sure if we've looked at this previously or if it would work in our case.

@jlengstorf jlengstorf changed the title [v2] CSS no longer inlined during development, causing FOUC [v2] Webpack V4 style-loader FOUC in development Aug 15, 2018
@KyleAMathews
Copy link
Contributor

@jlengstorf — we use mini-css-extract-plugin in v2 but yeah, we could probably use a similar technique.

@KyleAMathews
Copy link
Contributor

It'd need exploring.

@jlengstorf
Copy link
Contributor

Is this still considered a blocker for the V2 release? I'd personally vote in favor of not blocking the release, but I'm willing to be convinced otherwise.

@KyleAMathews
Copy link
Contributor

I don't think so.

@browne0
Copy link
Contributor

browne0 commented Aug 30, 2018

mini-css-extract-plugin is only used for production.

Maybe that's related to why it's happening?

https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/utils/webpack-utils.js#L181-L189

@nihgwu
Copy link
Contributor

nihgwu commented Aug 30, 2018

That's me who made the change to use style-loader instead of mini-css-extract-plugin in dev mode to enable hot reload, I don't think it's a blocker, as it's a common tweak in dev mode, yes we can still use mini-css-extract-plugin with css-hot-loader to support hot reload too, but I doubt if it's deserved, as per the document of mini-css-extract-plugin, it's supposed to be used in prod mode, I suspect if the plugin would slow down the build time(didn't test), so I'd rather use style-loader in dev mode instead

@Mesoptier
Copy link

Hi all! Not a Gatsby user here, but figured I'd chime in anyway since I have been dealing with a similar issue. According to this related issue on the style-loader package the FOUC can be fixed by disabling the sourceMap option for style-loader. (Or by enabling singleton, but I was still getting FOUC after doing so.)

@browne0
Copy link
Contributor

browne0 commented Sep 29, 2018

In that case, I can open a PR to change that in the webpack config.

it's currently only using source map when its not production.

https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/utils/webpack-utils.js#L195

@aspiers
Copy link

aspiers commented Jan 6, 2019

@browne0 Is there a PR for this yet? Thanks!

@gatsbot
Copy link

gatsbot bot commented Feb 15, 2019

Hiya!

This issue has gone quiet. Spooky quiet. 👻

We get a lot of issues, so we currently close issues after 30 days of inactivity. It’s been at least 20 days since the last update here.

If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!

Thanks for being a part of the Gatsby community! 💪💜

@gatsbot gatsbot bot added the stale? Issue that may be closed soon due to the original author not responding any more. label Feb 15, 2019
@gatsbot
Copy link

gatsbot bot commented Feb 26, 2019

Hey again!

It’s been 30 days since anything happened on this issue, so our friendly neighborhood robot (that’s me!) is going to close it.

Please keep in mind that I’m only a robot, so if I’ve closed this issue in error, I’m HUMAN_EMOTION_SORRY. Please feel free to reopen this issue or create a new one if you need anything else.

Thanks again for being part of the Gatsby community!

@mihaisavezi
Copy link

It's still happening

@lannonbr lannonbr added not stale and removed stale? Issue that may be closed soon due to the original author not responding any more. labels May 29, 2019
@lannonbr lannonbr reopened this May 29, 2019
@jsardev
Copy link

jsardev commented Jun 6, 2019

Any news on this? Just wasted a few hours because of this 😅

@ali-sao
Copy link

ali-sao commented Jun 12, 2019

@sarneeh same goes for me

@jlengstorf
Copy link
Contributor

@sarneeh @ali-sao do you have repos we can look at to see the error? Reproductions are really helpful here. Thanks!

@jsardev
Copy link

jsardev commented Jun 18, 2019

@jlengstorf Here you are https://github.com/sarneeh/gatsbyjs-gatsby-issues-6211. This seems like a problem with PostCSS plugin + Tailwind in my case. Don't know what it's like for other people here.

@jlengstorf
Copy link
Contributor

@sarneeh the page components get unmounted/remounted on each navigation, which is probably the culprit here.

I'd try this:

  1. Remove the styles from the page (here: https://github.com/sarneeh/gatsby-issue-6211/blob/master/src/pages/index.js#L3)
  2. Create a gatsby-browser.js in the project root and import them there instead:
    import './src/styles/index.css';

This will make the styles globally available and won't unmount/remount them.

@jsardev
Copy link

jsardev commented Jun 19, 2019

@jlengstorf Thanks for taking a look on this! But I'm still confused: why this is not happening when I just put plain CSS in the imported style?

@jlengstorf
Copy link
Contributor

@sarneeh I'm not sure, honestly. My guess would be that it is happening, but so fast that it's not noticeable with a single small CSS file.

@davidohlin
Copy link

I'm also having problems with FOUC, and I am using tailwind as well. I have moved my css import to gatsby-browser.js and that made it happen less frequent, but it still happens.

@jure
Copy link

jure commented Aug 26, 2019

For what it's worth, @sarneeh, I've tried to replicate this in your repo (https://github.com/sarneeh/gatsby-issue-6211), and it needed a few additional steps to run.

  1. I needed to install tailwindcss (^1.1.2)
  2. I needed to install gatsby-plugin-postcss (^2.1.5)

After this, I ran yarn develop, and could not replicate the FOUC in latest Chrome, Safari or Firefox, but I did manage to replicated it consistently with Firefox 66.0.3 (only on a cold load, with the cache cleared).

Worth checking if this is still an issue for you, using the new dependencies (and latest browsers).

@vladar
Copy link
Contributor

vladar commented Apr 27, 2020

I could reproduce this using example from #22640

The culprit is those lines in the style-loader: https://github.com/webpack-contrib/style-loader/blob/33aebed87de36efa3069067cee00141bebf4ebd4/lib/addStyles.js#L388-L397

Effectively link.href = URL.createObjectURL(blob); takes too long sometimes which makes styles to load after the page content. This is especially noticable with big styles and big source maps.

@LekoArts
Copy link
Contributor

We're only accepting critical security fixes for Gatsby v2 now and Gatsby v3 uses webpack@5 -- if you still see this issue in the latest version of Gatsby, please open a new issue with a minimal reproduction. Thanks!

@gatsbyjs gatsbyjs locked as resolved and limited conversation to collaborators Apr 21, 2021
@LekoArts LekoArts removed the not stale label May 7, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
help wanted Issue with a clear description that the community can help with. type: bug An issue or pull request relating to a bug in Gatsby
Projects
None yet
Development

No branches or pull requests