Semantic-UI + PurgeCSS(postcss)

Hey everyone.

I am trying to optimize a very simple site that was bootstrapped using CRA. I am bad with CSS so I use Semantic UI React components and the semantic-ui-css package. My bundle size is quite large and includes a lot of unused CSS as reported by Lighthouse.

File sizes after gzip:

  182.41 KB       build\static\js\2.2c0cec5e.chunk.js
  95.82 KB        build\static\css\2.003b56fe.chunk.css   
  8.34 KB (-1 B)  build\static\js\main.13de69e2.chunk.js  
  771 B           build\static\js\runtime-main.2a146b8e.js
  449 B           build\static\css\main.6b845f7c.chunk.css

I'm currently trying to configure the purgecss postcss plugin via @craco/craco but too much styling is being removed. Here is my postcss.config.js which I basically copy pasted from Tailwind documentation that includes some regex. Obviously this regex will not work with Semantic so I was hoping someone in the community might either have regex that works with Semantic + purgecss (very bad with regex) or a different solution to remove unused CSS from Semantic in React.

​

const purgecss = require('@fullhuman/postcss-purgecss')({
  // Specify the paths to all of the template files in your project
  content: ['./public/**/*.html', './src/**/*.css', './src/**/*.js'],

  // This is the function used to extract class names from your templates
  defaultExtractor: (content) => {
    // Capture as liberally as possible, including things like `h-(screen-1.5)`
    const broadMatches = content.match(/[^<>"'`\s]*[^<>"'`\s:]/g) || [];

    // Capture classes within other delimiters like .block(class="w-1/2") in Pug
    const innerMatches = content.match(/[^<>"'`\s.()]*[^<>"'`\s.():]/g) || [];

    return broadMatches.concat(innerMatches);
  },
});

module.exports = {
  plugins: [...(process.env.NODE_ENV === 'production' ? [purgecss] : [])],
};

1 comments · 75% upvoted · other discussions

comments

[deleted]

I have a setup that might be what you're looking for. My app is CRA, Tailwind, Semantic UI, Styled Components, and config via Craco. We're also lazy loading for code splitting.

What I did was move the PurgeCSS config to postcss.config.js:

``` const cssnano = require('cssnano'); const postcssPresetEnv = require('postcss-preset-env'); const purgecss = require('@fullhuman/postcss-purgecss');

module.exports = () => ({ plugins: [ postcssPresetEnv({ stage: 3, features: { 'custom-properties': { preserve: true, fallback: true, }, }, autoprefixer: { flexbox: true, grid: false, }, }), cssnano({ preset: [ 'default', { discardComments: { removeAll: true, }, }, ], }), purgecss({ content: ['./src//*.html', './src//.js', './src//.jsx', './src//*.ts', './src//.tsx', './public/index.html'], css: ['./src/styles/tailwind.css'], // This is the function used to extract class names from your templates defaultExtractor: (content) => { // Capture as liberally as possible, including things like h-(screen-1.5) const broadMatches = content.match(/[<>"'`\s][<>"'`\s:]/g) || [];

    // Capture classes within other delimiters like .block(class="w-1/2") in Pug
    const innerMatches = content.match(/[^<>"'`\s.()]*[^<>"'`\s.():]/g) || [];

    return broadMatches.concat(innerMatches);
  },
}),

], }); ```

Then load that config onto craco.config.js and add the PurgeCSS Webpack plugin:

``` const { resolve } = require('path'); const { realpathSync } = require('fs'); const glob = require('glob');

const { POSTCSS_MODES } = require('@craco/craco'); const PurgecssPlugin = require('purgecss-webpack-plugin');

const appDirectory = realpathSync(process.cwd()); const resolveApp = (relativePath) => resolve(appDirectory, relativePath);

module.exports = { style: { postcss: { mode: POSTCSS_MODES.file, }, }, webpack: { plugins: [ new PurgecssPlugin({ paths: [resolveApp('public/index.html'), ...glob.sync(${resolveApp('src')}/**/**/*, { nodir: true })], }), ], }, }; ```

Then running craco build should run PurgeCSS correctly for you.

Fair warning, we came across this issue this week and I didn't attempt to fix it until today. So, although PurgeCSS is working as expected, there are still some optimizations to be done to these configs. And I think the PurgeCSS config on postcss.config.js is redundant and could be removed.

Play around with this setup and see what works best for you.

Edit: Grammar.