Gatsby: Extract the CSS out of style tag in separate stylesheets

Created on 30 Sep 2017  路  16Comments  路  Source: gatsbyjs/gatsby

I would love to extract the CSS out style tags into separate stylesheets, I am using Bootstrap within my site and it's less than ideal to load the full bootstrap with subsequent visits of the user. Is there any plugin for gatsby which solves this, like ExtractTextPlugin for Webpack? I can't find one

question or discussion

Most helpful comment

This is the solution I'm using, if anyone wants an alternative.

if (process.env.NODE_ENV === "production") {
  for (const component of props.headComponents) {
    if (component.type === "style") {
      const index = props.headComponents.indexOf(component)
      const link = <link rel="stylesheet" href={component.props["data-href"]} />
      props.headComponents.splice(index, 1, link)
    }
  }
}

All 16 comments

Have you looked at using react-bootstrap?

There is also an example site here but never tried it.

Gatsby does extract CSS but inlines it into the HTML <head> for performance.

If you create a custom html.js, you can link to the generated css file if you'd like.

You might be interested in this approach though which automatically removes excess CSS https://github.com/rongierlach/gatsby-plugin-purify-css

In my case, it doesn't extract it at all.
gatsby.config.js

module.exports = {
  plugins: [
    'gatsby-plugin-react-helmet',
    'gatsby-plugin-sass'
  ],
};

layouts/index.js

import '../assets/sass/style.scss';

It works fine in development, but when running a production build it comes out completely unstyled with an empty style tag in the head. public/style.css is completely empty.

@3stacks try to see if you can reproduce your issue with the sass example app.

@KyleAMathews , are you talking about this example?
https://github.com/gatsbyjs/gatsby/tree/master/examples/using-sass

Does this exist as a starter, or do I just copy these files and run my gatsby tasks?

Just clone the repo and navigate to its directory. I'd love to make all the examples work as starters but that'll take some infrastructure work.

The sass example does work for me. I'll give it a shot converting the blog over to use that sass example tonight. I have a feeling this is just a bizarre edge case, because sass has been misbehaving from the start for me.

As I started migrating my stuff, I saw the stuff getting spit out into public/style.css, but when I look at the HTML I see this.

<style id="gatsby-inlined-css">[object Object]</style>

Closing this issue as it's fairly old and we have far too many open issues! If you have additional problems in this area, please open a new issue!

Hey @3stacks.
It looks like solution not to hard to maintain by html.js extraction.
Just follow https://www.gatsbyjs.org/docs/custom-html/

And then replace default logic around css like:
Before:

    if (process.env.NODE_ENV === `production`) {
      css = (
        <style
          id="gatsby-inlined-css"
          dangerouslySetInnerHTML={{ __html: stylesStr }}
        />
      )
    }

After:

    if (process.env.NODE_ENV !== `production`) {
      css = (
        <style
          id="gatsby-inlined-css"
          dangerouslySetInnerHTML={{ __html: stylesStr }}
        />
      )
    } else {
      css = (<link rel="stylesheet" href="/styles.css"/>)
    }

This solution doesn't cover any pathPrefix, but as initial solution can help to reduce size of all html files

Thanks for the info @Pencroff! I started again from a new starter and that solved the problem for me, but good for the public record.

Hi @Pencroff thanks for the tip! I have a similar requirement and would need to extract the CSS into separate stylesheets. However, where is stylesStr being declared from?

Hi @Pencroff thanks for the tip! I have a similar requirement and would need to extract the CSS into separate stylesheets. However, where is stylesStr being declared from?

I have on top of html.js code like:

let stylesStr
if (process.env.NODE_ENV === `production`) {
  try {
    stylesStr = require(`!raw-loader!../public/styles.css`)
  } catch (e) {
    console.log(e)
  }
}

Thanks @Pencroff

For some reason when I run build, a styles.css file is not created but something like component---src-pages-index-js.341e385fbf9137261e9d.css is created as a stylesheet.

I'm using the sass-example from Gatsby with the following in the config:

module.exports = {
  plugins: [
    `gatsby-plugin-sass`,
    {
      resolve: `gatsby-plugin-google-analytics`,
      options: {
        trackingId: `UA-93349937-2`,
      },
    },
    `gatsby-plugin-offline`,
  ],
}

Dependencies:

"dependencies": {
  "gatsby": "^2.0.0",
  "gatsby-plugin-google-analytics": "^2.0.5",
  "gatsby-plugin-offline": "^2.0.5",
  "gatsby-plugin-sass": "^2.0.1",
  "node-sass": "^4.9.0",
  "raw-loader": "^0.5.1",
  "react": "^16.3.0",
  "react-dom": "^16.3.0",
  "tachyons-sass": "^4.7.1"
}

This is the solution I'm using, if anyone wants an alternative.

if (process.env.NODE_ENV === "production") {
  for (const component of props.headComponents) {
    if (component.type === "style") {
      const index = props.headComponents.indexOf(component)
      const link = <link rel="stylesheet" href={component.props["data-href"]} />
      props.headComponents.splice(index, 1, link)
    }
  }
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

brandonmp picture brandonmp  路  3Comments

theduke picture theduke  路  3Comments

KyleAMathews picture KyleAMathews  路  3Comments

dustinhorton picture dustinhorton  路  3Comments

benstr picture benstr  路  3Comments