diff --git a/docusaurus/docs/post-processing-css.md b/docusaurus/docs/post-processing-css.md index 1a456b9f1c5..0281811c754 100644 --- a/docusaurus/docs/post-processing-css.md +++ b/docusaurus/docs/post-processing-css.md @@ -42,3 +42,19 @@ If you need to disable autoprefixing for some reason, [follow this section](http If you'd like to opt-in to CSS Grid prefixing, [first familiarize yourself about its limitations](https://github.com/postcss/autoprefixer#does-autoprefixer-polyfill-grid-layout-for-ie). To enable CSS Grid prefixing, add `/* autoprefixer grid: autoplace */` to the top of your CSS file. + +### Customizing PostCSS Config + +However, if you want to add custom plugins, add a `postcss.config.js` file to the root of your project. It will replace the internal CRA postcss plugins. + +You can read more about common PostCSS Config [here](https://github.com/michael-ciniawsky/postcss-load-config). + +```js +module.exports = { + parser: 'sugarss', + map: false, + plugins: { + 'postcss-plugin': {}, + }, +}; +``` diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index 4455dc719bb..6203fa4dd5c 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -36,7 +36,15 @@ const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin' // @remove-on-eject-begin const getCacheIdentifier = require('react-dev-utils/getCacheIdentifier'); // @remove-on-eject-end -const postcssNormalize = require('postcss-normalize'); +const postcssLoadConfig = require('postcss-load-config'); + +const hasPostcssConfig = (() => { + try { + return !!postcssLoadConfig.sync(); + } catch (_error) { + return false; + } +})(); const appPackageJson = require(paths.appPackageJson); @@ -110,19 +118,23 @@ module.exports = function (webpackEnv) { // Necessary for external CSS imports to work // https://github.com/facebook/create-react-app/issues/2677 ident: 'postcss', - plugins: () => [ - require('postcss-flexbugs-fixes'), - require('postcss-preset-env')({ - autoprefixer: { - flexbox: 'no-2009', - }, - stage: 3, - }), - // Adds PostCSS Normalize as the reset css with default options, - // so that it honors browserslist config in package.json - // which in turn let's users customize the target behavior as per their needs. - postcssNormalize(), - ], + ...(hasPostcssConfig + ? {} + : { + plugins: () => [ + require('postcss-flexbugs-fixes'), + require('postcss-preset-env')({ + autoprefixer: { + flexbox: 'no-2009', + }, + stage: 3, + }), + // Adds PostCSS Normalize as the reset css with default options, + // so that it honors browserslist config in package.json + // which in turn let's users customize the target behavior as per their needs. + require('postcss-normalize')(), + ], + }), sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment, }, }, diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index 8888ebc9e31..554e9fc4678 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -64,6 +64,7 @@ "pnp-webpack-plugin": "1.6.4", "postcss-flexbugs-fixes": "4.2.1", "postcss-loader": "3.0.0", + "postcss-load-config": "2.1.0", "postcss-normalize": "8.0.1", "postcss-preset-env": "6.7.0", "postcss-safe-parser": "4.0.2", diff --git a/test/fixtures/postcss-config/.disable-pnp b/test/fixtures/postcss-config/.disable-pnp new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/fixtures/postcss-config/__snapshots__/index.test.js.snap b/test/fixtures/postcss-config/__snapshots__/index.test.js.snap new file mode 100644 index 00000000000..717723f5eac --- /dev/null +++ b/test/fixtures/postcss-config/__snapshots__/index.test.js.snap @@ -0,0 +1,6 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`builds with custom postcss config 1`] = ` +"body{background:#056ef0} +/*# sourceMappingURL=main.9b96d08a.chunk.css.map */" +`; diff --git a/test/fixtures/postcss-config/index.test.js b/test/fixtures/postcss-config/index.test.js new file mode 100644 index 00000000000..089a6be2b7e --- /dev/null +++ b/test/fixtures/postcss-config/index.test.js @@ -0,0 +1,17 @@ +const testSetup = require('../__shared__/test-setup'); + +const fs = require('fs-extra'); +const globby = require('globby'); +const path = require('path'); + +test('builds with custom postcss config', async () => { + await testSetup.scripts.build(); + + const buildDir = path.join(testSetup.testDirectory, 'build'); + const cssFile = path.join( + buildDir, + globby.sync('**/*.css', { cwd: buildDir }).pop() + ); + + expect(fs.readFileSync(cssFile, 'utf8')).toMatchSnapshot(); +}); diff --git a/test/fixtures/postcss-config/package.json b/test/fixtures/postcss-config/package.json new file mode 100644 index 00000000000..463b1d8c5df --- /dev/null +++ b/test/fixtures/postcss-config/package.json @@ -0,0 +1,7 @@ +{ + "dependencies": { + "react": "latest", + "react-dom": "latest", + "postcss-simple-vars": "latest" + } +} diff --git a/test/fixtures/postcss-config/postcss.config.js b/test/fixtures/postcss-config/postcss.config.js new file mode 100644 index 00000000000..e9045e1ea34 --- /dev/null +++ b/test/fixtures/postcss-config/postcss.config.js @@ -0,0 +1,3 @@ +module.exports = { + plugins: [require('postcss-simple-vars')], +}; diff --git a/test/fixtures/postcss-config/src/index.css b/test/fixtures/postcss-config/src/index.css new file mode 100644 index 00000000000..3f156733094 --- /dev/null +++ b/test/fixtures/postcss-config/src/index.css @@ -0,0 +1,5 @@ +$blue: #056ef0; + +body { + background: $blue; +} diff --git a/test/fixtures/postcss-config/src/index.js b/test/fixtures/postcss-config/src/index.js new file mode 100644 index 00000000000..c233f23b66c --- /dev/null +++ b/test/fixtures/postcss-config/src/index.js @@ -0,0 +1,5 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import './index.css'; + +ReactDOM.render(
, document.getElementById('root'));