Gatsby v2 removes the global layout and we now have to wrap every component into a normal React component, let's say from src/components/layout.js.
From this file I include some stylesheets using something like import "./design.css". The problem is that every time a page is loaded (for instance using window.___loader.hovering when hovering a link), the whole CSS file is reloaded (even if it's already there) including linked resources such as images and fonts. This causes a page blink.
What is the Gatsby v2 way, now that the global layout is gone, to include a global stylesheet that isn't re-downloaded when a new page is loaded?
The best place to load global styles now is in your gatsby-browser.js as that's loaded at the root of your site.
We need to document that in the upgrade guide. Please try out this change and if it feels good to everyone, we can close this issue by updating the guide.
I spent a lot of time trying to solve this apparently simple issue and I didn't think of gatsby-browser.js, happy to find there is such a simple solution! But you're right that this definitely needs to be documented.
So apparently adding the import line isn't enough for the file to be executed in the browser (and the style to be loaded) and we need to add a stub like exports.onClientEntry = () => {};. If the goal is to have gatsby-browser.js be a main.js for the client maybe this behavior should be changed?
Oh... hmm that's odd. I'll look into this soon-ish then.
Also welcome anyone else who wants to investigate why gatsby-browser.js isn't loading css
@KyleAMathews I am also being affected by this. My fonts are loading many times and flashing on load in production.
@mquandalle did you find a way to get this to work in gatsby-browser.js? You mentioned a stub.
@mquandalle Actually, I was just able to get this to work. Putting this (and only this) in gatsby-browser.js worked for me and loaded all of the appropriate packages and files:
require("./src/styles/index.scss");
require("./src/fonts/fonts.css");
require("svgxuse");
Edit: This worked on dev, but not in production...
Edit 2: Ah yes, I understand now. The shim (exports.onClientEntry = () => {};) is required for this to work introduction. Works fine in dev without the shim.
@KyleAMathews Would you still like someone to look into why gatsby-browser.js isn't loading css (production)?
That'd be great!
Two things. First, standard css imports seem to be working fine for me in gatsby-browser.js. The following is showing up correctly for me on the frontend in development:
import styles from './src/global.scss';
However, I think there may be some issues with gatsby-browser.js in production other than strictly not loading css. For instance, my provider is working in development but not production. My build is failing and notifying me that my 'AppState' is not provided by a provider:
export const replaceRouterComponent = ( { history } ) => {
return ( { children } ) => (
<Provider AppState={ AppState }>
<Router history={ history }>{ children }</Router>
</Provider>
);
};
I might open a separate issue for this specifically, but it might help narrow down the problem here.
@kmcaloon the problem with the later is we don't support es6 import/export for APIs — a restriction which we can/should release. I'm not sure if there's an issue for that but it's a reasonable restriction to fix. Use exports.replaceRouterComponent for now to get that working.
@KyleAMathews. Thanks, I think what confused me was this #4452 and the fact that it is working in development and not production?
Oh hmmm I didn't think we'd got that working. Did we @m-allanson @pieh?
@KyleAMathews, since es6 imports are not supposed to be supported by the APIs, then do you know why most examples around are using them?
Eg.
I'll also try to dig up some other examples I've seen in some repos
It looks like we're talking about three different things in this issue, so I'm going to break out new issues so we don't lose track of things.
gatsby-browser.js isn't applying imports without a stub function (created #6759 to track this)gatsby-*.js files in production (created #6761)I'll port the conversation over where relevant. Please post any follow-up conversation in the appropriate issue to help us keep things straight.
Thanks!
Once this is done we should update the tutorial to handle this too.
There's a stub guide docs page for this too https://next.gatsbyjs.org/docs/creating-global-styles/
Is this now the recommended way to do this?
https://next.gatsbyjs.org/docs/creating-global-styles/
Because this looks like gatsby-browser.js is still the way to go
https://www.gatsbyjs.org/tutorial/part-two/#using-global-styles
@AlchemyUnited both options work. @gatsbyjs/core will global styles in a component unmount/remount on page changes, or is the SSR step smart enough to know it's used everywhere?
@jlengstorf - if the tutorial version works then there's something wrong with me :) because I was not able to get it work. I found this thread - and the alt solution - while trying to troubleshoot. No errors, etc. It just wouldn't work (e.g., recognize and apply global styles). Once I went with the alt version (link 1) I was fine.
Hmmm... definitely need to check into that. It _should_ work. 😕
Would also like to know what the recommended pattern is now. IIRC in v1 importing globals in gatsby-browser.js was recommended to avoid reloading styles etc from layouts. Now that layouts have been ditched in v2 is that still the case? Or does Gatsby do some magic to avoid re-rendering global styles from inside components? I hope the latter isn't the case, sounds fragile.
Also did the markup demo / tut and had to use this:
the line of code in the demo with dangerouslySetInnerHTML doesn't work. Somewhere I found I should use the above.
Between this and the global styles issue (above), I musta used 50% of the time I put into the tutorial chasing my own tail. Time I didn't have but I have some uses for Gatsby and had to power through. Nonetheless, very frustrating :(
I'm still having an issue with this. I've imported the global SCSS style sheet into gatsby-browser.js as well as tried to import it into layout.js still no luck. I've only managed to get the style body {background: #3e3e3e;} to work once but once the page refreshes the styles get overridden. Any ideas? I've tried the solutions suggested above and have had zero luck unless I use !important.
Do we have a concensus on where to put <GlobalStyle /> ?
gatsby-browser.js or layout.js ?
The overwhelming documentation says layout.js
But some nay-sayers are stating that without putting it higher up... like gatsby-browser.js you may risk cross-route css animations from breaking.
I believe we would be in this group wanted our cake and eating it.
If we put it only in gatsby-browser.js, doesn't that mean that its client-side only and not SSR'd ?
Should it not go in gatsby-ssr.js
It would be nice to get an answer on this(iDVB's questions) for 2020... I just created a pull request to update the link on the documentation for the shared layout component method and I found that the link is still pointing to the Gatsby v1 "special layout component" method... this no longer works in v2.
Now I've found this issue and I see the comment from Kyle Matthews from 2018, and I am wondering if the documentation just never got updated after version 2 came out. Is there any reason not to use gatsby-browser.js for global css?
There is also a tutorial that recommends using a shared layout component over gatsby-browser.js, and a "recipe page" that advises you to use a shared layout component for global css only IF you are using CSS-in-JS... I'm new on this but I don't entirely understand how global css relates to CSS-in-JS here(Is the documentation talking about a case where you want to use CSS-in-JS for global styles or any CSS-in-JS at all?)
My initial impression was that anything in gatsby-browser.js would run on the client browser, so import'ing the css in gatsby-browser.js would cause the css files to be pulled in dynamically by the client browser's javascript. However, after looking at the build files of a project I have where gatsby-browser.js imports css files, I saw that all the site's css is combined and minified into an inline style tag in the head of each page's index.html file... suddenly this issue makes a lot more sense.
Unless I am missing something(very well could be), it seems like there is no downside to importing global css files through gatsby-browser.js...
Now I am wonder what Gatsby does with the data-href attribute that links to the styles.XXX.css file with all same minified css... there is more magic yet to be uncovered for me... help? --Edit-- Well I found one use for the data-href attribute in this comment -- that code running in html.js replaces the inline style tag with a <link rel="stylesheet" href="/styles.XXX.css" /> element... :)
Most helpful comment
@mquandalle Actually, I was just able to get this to work. Putting this (and only this) in
gatsby-browser.jsworked for me and loaded all of the appropriate packages and files:Edit: This worked on dev, but not in production...
Edit 2: Ah yes, I understand now. The shim (
exports.onClientEntry = () => {};) is required for this to work introduction. Works fine in dev without the shim.