-
Notifications
You must be signed in to change notification settings - Fork 10.3k
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] How to manually specify postcss plugins? #5778
Comments
Good question - there isn't yet. This step is kind of a placeholder, the plan is to add a new plugin that will allow you to configure PostCSS for your project with a plain old PostCSS config file. Check out the issue discussing this: #3284 If you're comfortable configuring webpack, you could do this using Gatsby's |
I've tried to add Additionally, after adding |
EditI realize that you can use OriginalI am having some issues migrating from v1 to v2. I trying to reconfigure the
I think the problem I am running into is that the UsageMy usage is simply the following in
And then in my Since cssnext is being deprecated I am trying to use https://preset-env.cssdb.org/ instead. Basically I am just migrating from v1 to v2 and this is blocking me sadly. |
As soon as I add any type of loader I am getting errors. It doesn't matter if I only have one loader or a ton.
The error:
|
After trying to make this work for a while I am still getting the above error. In the default webpack config. When using Start Config
End Config
|
This is finally working with me with const path = require('path')
const webpack = require('webpack') // eslint-disable-line import/no-extraneous-dependencies
const postcssCssnext = require('postcss-cssnext')
const poscssImport = require('postcss-import')
exports.onCreateWebpackConfig = ({ actions, loaders, getConfig }) => {
actions.setWebpackConfig({
module: {
rules: [
{
test: /\.example/,
use: [{ loader: 'raw-loader' }],
},
{
test: /\.css$/,
use: [
loaders.miniCssExtract(),
// // 0 => no loaders (default); 1 => postcss-loader; 2 => postcss-loader, sass-loader
loaders.css({ importLoaders: 1 }),
loaders.postcss({
ident: 'postcss',
plugins: () => [poscssImport(), postcssCssnext()],
}),
],
},
],
}
})
const configAfterSettings = getConfig()
// Losing my mind here.
const finalRules = configAfterSettings.module.rules.filter(rule => {
if (Object.prototype.hasOwnProperty.call(rule, 'oneOf')) {
// Nuke this rule.
return JSON.stringify(rule).indexOf('style-loader') === -1
}
return true
})
// So much for immutability.
configAfterSettings.module.rules = finalRules
actions.replaceWebpackConfig(configAfterSettings)
} |
@jeroenransijn nice! Next steps would be using https://www.npmjs.com/package/postcss-load-config to load your plugins from a |
@jeroenransijn Hey! Do you have any idea why doing this throws an error: exports.onCreateWebpackConfig = ({ actions, rules }) => {
actions.setWebpackConfig({
module: {
rules: [rules.postcss()],
},
});
}; Even though I'm not specifying any postcss plugins there, I'm still getting an error very similar to yours:
I'll later try your solution, even though it looks a bit complex ;) Do you know if it replaces postcss config for all Gatsby stages? I'm not sure if it's really true, but I might need different postcss plugins in development and production builds (though maybe I won't if e.g. css-loader can minify css as well) |
@szimek that is exactly the issue I ran into. The main problem is that there is already a loader for CSS/CSS modules in the default Gatsby Webpack config. The following super ugly hack gets the config, nukes that rule, and then replaces the Webpack config: const configAfterSettings = getConfig()
// Losing my mind here.
const finalRules = configAfterSettings.module.rules.filter(rule => {
if (Object.prototype.hasOwnProperty.call(rule, 'oneOf')) {
// Nuke this rule.
return JSON.stringify(rule).indexOf('style-loader') === -1
}
return true
})
// So much for immutability.
configAfterSettings.module.rules = finalRules
actions.replaceWebpackConfig(configAfterSettings) I talked to Kyle about some ideas around this. Imo, preferably we would have something inside of Gatsby to nuke this rule in a more graceful matter. The two following things come to mind: actions.removeDefaultWebpackCSSLoader() Or something more like the following to allow disabling other default loaders. Although I am not sure if there is a use case for this. actions.setDefaultWebpackLoaders({
css: false,
}) @KyleAMathews I don't mind giving the plugin a try, but I think we should have something in Gatbsy to do the above without having to rely on hacks. It might be I am missing something here that would be more graceful without changing Gatsby.. |
I don't think there should be problem generally with adding another css loader even without removing the existing one, It should just handle the files first leaving nothing for the later plugin to handle unless i'm missing something (believe i've done this is exact thing before without problem) I'm wondering if errors are do to not handling the various build stages correctly. It's not enough to add a new loader ,you need to add them at the right stages, like the existing one (and less, sass, style plugins as well). |
@jquense I am not all that seasoned in Webpack so I might be missing something obvious. When I was trying this I was actually surprised I was able to solve this problem by removing the current loader. I was expecting Webpack to be able to understand what was going on. Additionally, I think |
Currently Gatsby has slightly different webpack rules for handling CSS files depending on the command ( I'm not sure if PostCSS config needs to change depending on the command or stage, but would it be enough if it was possible to completely replace PostCSS loader config only (e.g. via On one hand it probably is a bad idea to provide specific options for each loader (this might get quickly out of hand, e.g. it would be great if I could change Gatsby does provide |
@szimek @jeroenransijn I have created a simple plugin which does the followings:
Now we can use Please check https://github.com/mdreizin/gatsby-plugin-postcss |
@mdreizin do you mind helping maintain your plugin here in this repo? I'd been planning on writing something similar to this soon :-) I was planning on using https://github.com/michael-ciniawsky/postcss-load-config to add support for additional ways of handling postcss config. |
If you're amenable to this, just PR the plugin here and add me as an owner on NPM (kylemathews) |
@KyleAMathews No problems, I will make a new PR within a hour. |
@mdreizin thanks so much! This is amazing! @KyleAMathews as a note this is still removing the current rule https://github.com/mdreizin/gatsby-plugin-postcss/blob/master/src/gatsby-node.js#L9 : originalConfig.module.rules = originalConfig.module.rules.filter(rule => {
if (Array.isArray(rule.oneOf)) {
return JSON.stringify(rule).indexOf('postcss-loader') === -1;
}
return true;
}); I am okay with this, but would like to highlight it might be nice to make it a feature of the framework to do this safely. |
@jeroenransijn I also agree that we need to have some methods (or an approach) which help to remove existing loaders. |
@KyleAMathews I have already granted NPM permissions and created a new PR. It is a start point for further discussions and improvements ;) I thought about using |
@mdreizin Thank you! |
@jeroenransijn I could definitely use this! Until Gatsby's postcss customization is figured out (including different configs in development vs. production), I've been:
With Webpack v1 in Gatsby v1, I was able to remove the default loader at each stage and redefine it like this: exports.modifyWebpackConfig = ({ config, stage }) => {
switch (stage) {
case `develop`:
// Remove default CSS loader
config.removeLoader(`css`)
// Remove postcss from Gatsby's dev process and ignore partials
config.loader(`css`, {
test: /\.css$/,
exclude: [
/src\/styles\/base/,
/src\/styles\/builds\/after-purgecss/,
/src\/styles\/components/,
/src\/styles\/plugins/,
/src\/styles\/reset/,
/src\/styles\/supports/,
/src\/styles\/utilities/
],
loaders: [`style`, `css`]
})
break
case `build-css`:
// Remove default CSS loader
config.removeLoader(`css`)
// Remove postcss from Gatsby's build process and ignore partials
config.loader(`css`, {
test: /\.css$/,
exclude: [
/src\/styles\/base/,
/src\/styles\/builds\/after-postcss/,
/src\/styles\/components/,
/src\/styles\/plugins/,
/src\/styles\/reset/,
/src\/styles\/supports/,
/src\/styles\/utilities/
],
loader: ExtractTextPlugin.extract([`css?minimize`])
})
break
}
return config
} Unfortunately, this functionality does not seem to be available with Webpack v4 in Gatsby v2. Any tips on how to duplicate this functionality in Gatsby v2 would be very helpful! (A plugin that enables the same functionality without having to use the CLI tools or modify the Webpack config directly would obviously be fantastic.) |
@ooloth none of that should be necessary in v2, Gatsby does not include postcss except to autoprefix, which shouldn't affect any style flow. v1 had a fairly prescriptive postcss loader by default, not that has been removed in v2. I'm not sure what all your excludes are for tho, can you talk about why you need them? |
@jquense Thanks for the clarification about postcss in v2. In my case, I need to run the Regarding your question about all the excludes, they are there to facilitate my CSS workflow, which currently consists of one In my layout component, I import the relevant CSS file for the current environment: // Use PostCSS stylesheet in development and PostCSS/PurgeCSS stylesheet in production:
switch (process.env.NODE_ENV) {
case `development`:
require(`../styles/builds/after-postcss/output.css`)
break
case `production`:
require(`../styles/builds/after-purgecss/output.css`)
break
} Basically, I just want to run a specific sequence of postcss plugins in development and then the same postcss plugins + purgecss in production. In v1, I found the development spreadsheet would unfortunately still be inlined in production unless I added the excludes. I opted to "exclude" irrelevant files (rather than explicitly testing just for relevant ones) to make sure Gatsby still picked up CSS produced by other packages (e.g. In v2, the webpack setup in my previous comment no longer works and once again the development version of my CSS is loading in production (slowing page load as it includes many unused styles). I'm open to any advice here! A cleaner approach that just uses a single stylesheet (instead of separate dev and production stylesheets) and uses webpack to run postcss on it for development and postcss + purgecss for production would be lovely. |
You shouldn't need to update the existing loader then, adding a new loader on the end would be enough. You can either piggyback on the existing loader by adding just postcss loader (no css or style) or do the whole cahin and the files will be handled before the default one effectively ignore it.
I think you are being too smart for webpack, try switching your |
Can you clarify which (I had one in my |
@jquense You were absolutely right! Updating from // Use PostCSS stylesheet in development and PostCSS/PurgeCSS stylesheet in production:
if (process.env.NODE_ENV === `development`) {
require(`../styles/builds/after-postcss/output.css`)
} else if (process.env.NODE_ENV === `production`) {
require(`../styles/builds/after-purgecss/output.css`)
} No idea why that worked, but I'm happy. :) Any advice about how to apply purgeCSS only in production (either via webpack or postcss) without having to use the CLI tools and generate two different stylesheets? |
Glad that is working. If you can point me to a minimal purgeCSS setup I might be able to recommend something. But I'm not really familiar with it |
@jquense Thanks! PurgeCSS is a tool that removes unused selectors from a stylesheet to reduce file size (useful when using utility-class libraries like Tachyons or TailwindCSS). It's like purifyCSS (which there is already a Gatsby plugin for), but much more effective. How to achieve the minimal setup is the question, but here are examples of each option: I currently use the CLI tool (see example) to take the "after-postcss" version of my stylesheet and generate the "after-purgecss" version for production before each PurgeCSS can also be used with Webpack (see example) or postcss (see example). Could you possibly recommend how to integrate one of these approaches with Gatsby (in production only)? I'm a bit confused about exactly how to add the webpack example to Gatsby's v2 webpack config or how to add a production-only postcss plugin to the upcoming (Thanks in advance!) |
It looks like you need to include the plugin you can use the gatsby API and exports.onCreateWebpackConfig = ({ stage, actions }) => {
if (stage.includes('develop')) return
actions.setWebpackConfig({
plugins: [new PurgecssPlugin(yourOptions)]
})
} |
@jquense Thanks again! That got me started and I got PurgeCSS working in production like this: const PurgeCssPlugin = require(`purgecss-webpack-plugin`)
const path = require(`path`)
const glob = require(`glob`)
const PATHS = {
src: path.join(__dirname, `src`)
}
// Nonessential options removed for brevity
const purgeCssConfig = {
paths: glob.sync(`${PATHS.src}/**/*.js`, { nodir: true }),
}
exports.onCreateWebpackConfig = ({ actions, stage }) => {
if (stage.includes(`develop`)) return
// Add PurgeCSS in production
if (stage.includes(`build`)) {
actions.setWebpackConfig({
plugins: [new PurgeCssPlugin(purgeCssConfig)]
})
}
} Now my layout component can just import one file (generated by the postcss CLI) instead of using the conditional loading logic above: import '../styles/builds/after-postcss/output.css' I tried add adding some of the postcss examples above to |
I just noticed that the production css produced by Any tips how to minify the CSS output in production? |
As of the official release of v2 PostCSS seems to work like a charm. I started off configuring various PostCSS plugins myself just to find out everything is done through Here is the plugin config that is working well for me:
|
I read the new doc about migrating to v2 (https://v2--gatsbyjs.netlify.com/docs/migrating-from-v1-to-v2/#manually-specify-postcss-plugins)
I would like to try v2 alpha, but not sure how to configure postcss plugins.
Is there any more detailed example on how to manually configure postcss plugins?
Thanks.
The text was updated successfully, but these errors were encountered: