Gatsby: custom webpack config fails / how to mini-css-extract?

Created on 8 Nov 2018  路  4Comments  路  Source: gatsbyjs/gatsby

Hi

I need to reuse the css Gatsby is building and would like to output it to a separate css file. In the past I've used the mini-css-extract plugin with webpack, but adding this to Gatsby doesnt work as I'd hoped, i think because Gatsby already uses it internally. Any ideas how i can get my css output to a file?

needs more info

Most helpful comment

Ok so for the record, here's how to get Gatsby to build multiple named stylesheets and use them instead of inlining the css into the head of the html.

There are 3 things you need to do:

1) modify html.jsto hard link to the built files

import React from "react"
import PropTypes from "prop-types"

export default class HTML extends React.Component {
  render() {
    let headComponents = this.props.headComponents
    let css
    if (process.env.NODE_ENV == `production`) {
      headComponents = headComponents.filter(component => component.type !== 'style')
      css = (<><link rel="stylesheet" href="/foo.css"/><link rel="stylesheet" href="/bar.css"/></>)
    }
    return (
      <html {...this.props.htmlAttributes}>
        <head>
          <meta charSet="utf-8" />
          <meta httpEquiv="x-ua-compatible" content="ie=edge" />
          <meta
            name="viewport"
            content="width=device-width, initial-scale=1, shrink-to-fit=no"
          />
          {headComponents}
          {css}
        </head>
        <body {...this.props.bodyAttributes}>
          {this.props.preBodyComponents}
          <div
            key={`body`}
            id="___gatsby"
            dangerouslySetInnerHTML={{ __html: this.props.body }}
          />
          {this.props.postBodyComponents}
        </body>
      </html>
    )
  }
}

HTML.propTypes = {
  htmlAttributes: PropTypes.object,
  headComponents: PropTypes.array,
  bodyAttributes: PropTypes.object,
  preBodyComponents: PropTypes.array,
  body: PropTypes.string,
  postBodyComponents: PropTypes.array,
}

2) modify gatsby-node.js to add new entry points

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

exports.onCreateWebpackConfig = ({
  actions,
  stage,
  getConfig
}) => {
  // needed to output correctly-named css
  actions.setWebpackConfig({
    plugins: [new MiniCssExtractPlugin({})],
  })
   // needed to bodge in new css entry points
  if (stage.includes('javascript')) {
    let config = getConfig()
    config.entry["foo"] = './src/css/entry-points/foo.css'
    config.entry["bar"] = './src/css/entry-points/bar.css'
    actions.replaceWebpackConfig(config)
  }
}

3) make HMR / gatsby develop work by modifying gatsby-browser.js to include the entry points. this is a bit unsatisfactory but it works for my case. ymmv

import "./src/css/entry-points/foo.css"
import "./src/css/entry-points/bar.css"

All 4 comments

@gswirrl can you please provide environment information for your project by running gatsby info --clipboard?

@gswirrl mini-css-extract-plugin should support extracting several files, I'll check this.

Ok so for the record, here's how to get Gatsby to build multiple named stylesheets and use them instead of inlining the css into the head of the html.

There are 3 things you need to do:

1) modify html.jsto hard link to the built files

import React from "react"
import PropTypes from "prop-types"

export default class HTML extends React.Component {
  render() {
    let headComponents = this.props.headComponents
    let css
    if (process.env.NODE_ENV == `production`) {
      headComponents = headComponents.filter(component => component.type !== 'style')
      css = (<><link rel="stylesheet" href="/foo.css"/><link rel="stylesheet" href="/bar.css"/></>)
    }
    return (
      <html {...this.props.htmlAttributes}>
        <head>
          <meta charSet="utf-8" />
          <meta httpEquiv="x-ua-compatible" content="ie=edge" />
          <meta
            name="viewport"
            content="width=device-width, initial-scale=1, shrink-to-fit=no"
          />
          {headComponents}
          {css}
        </head>
        <body {...this.props.bodyAttributes}>
          {this.props.preBodyComponents}
          <div
            key={`body`}
            id="___gatsby"
            dangerouslySetInnerHTML={{ __html: this.props.body }}
          />
          {this.props.postBodyComponents}
        </body>
      </html>
    )
  }
}

HTML.propTypes = {
  htmlAttributes: PropTypes.object,
  headComponents: PropTypes.array,
  bodyAttributes: PropTypes.object,
  preBodyComponents: PropTypes.array,
  body: PropTypes.string,
  postBodyComponents: PropTypes.array,
}

2) modify gatsby-node.js to add new entry points

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

exports.onCreateWebpackConfig = ({
  actions,
  stage,
  getConfig
}) => {
  // needed to output correctly-named css
  actions.setWebpackConfig({
    plugins: [new MiniCssExtractPlugin({})],
  })
   // needed to bodge in new css entry points
  if (stage.includes('javascript')) {
    let config = getConfig()
    config.entry["foo"] = './src/css/entry-points/foo.css'
    config.entry["bar"] = './src/css/entry-points/bar.css'
    actions.replaceWebpackConfig(config)
  }
}

3) make HMR / gatsby develop work by modifying gatsby-browser.js to include the entry points. this is a bit unsatisfactory but it works for my case. ymmv

import "./src/css/entry-points/foo.css"
import "./src/css/entry-points/bar.css"

(so this issue can be closed :-)

Was this page helpful?
0 / 5 - 0 ratings