DEV Community

Thomas Ledoux
Thomas Ledoux

Posted on

Shipping minimal CSS with Next.js + purgeCSS

For a new project I'll be working on, the company asked to work with Bootstrap to be able to use the built-in grid, utility classes etc.
When I think of Bootstrap, I think: a lot of CSS being added to the project which is never used.

With the latest versions of Bootstrap, we have the possibility to only import the SCSS/LESS files for the features we will be using.
For example:

@import "~bootstrap/scss/grid";
@import "~bootstrap/scss/tables";
@import "~bootstrap/scss/forms";
Enter fullscreen mode Exit fullscreen mode

The problem with this approach is that these separate files still include a lot of CSS we will not be using in our application.

So what I'd like to do instead, is import the whole bootstrap SCSS, and then delete the unused CSS when building the production output:

@import '~bootstrap/scss/bootstrap';
Enter fullscreen mode Exit fullscreen mode

With this setup, the generated CSS has this size: cssbeforepurge

This is a big CSS chunk for the one class from Bootstrap we're using:

export default function Home() {
  return (
    <div className="container">
      <span>Test</span>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

So it would be nice to get rid of this CSS in our production build.
To achieve this, we'll be using purgeCSS.

We just need to add a postcss.config.js file to override the default postCSS config Next.js uses (https://nextjs.org/docs/advanced-features/customizing-postcss-config).

Our postcss.config.js will look like this:

module.exports = {
  "plugins": [
    "postcss-flexbugs-fixes",
    [
      "postcss-preset-env",
      {
        "autoprefixer": {
          "flexbox": "no-2009"
        },
        "stage": 3,
        "features": {
          "custom-properties": false
        }
      }
    ],
    [
      '@fullhuman/postcss-purgecss',
      {
        content: [
            './pages/**/*.{js,jsx,ts,tsx}',
            './components/**/*.{js,jsx,ts,tsx}'
        ],
        defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || [],
        safelist: ["html", "body"]
      }
    ],
  ]
}
Enter fullscreen mode Exit fullscreen mode

Don't forget to install the node_modules which are used by the postCSS config! (postcss-flexbugs-fixes, @fullhuman/postcss-purgecss, postcss-preset-env, autoprefixer).

When all this is done, you can create a new Next.js build (npm run build) and have the following result:
cssafterpurge

Inside the CSS output, it only includes the CSS for the container class, and the CSS variables used by Bootstrap.

That's a lot of CSS gone! Mission accomplished :-).

Top comments (7)

Collapse
 
fullstak profile image
Bram Hammer

Since this is quite high in google with the terms nextjs postcss i wanted to give an updated piece of code.

Next.js > 9.3 setup:

  1. Install required packages

npm i -D postcss-flexbugs-fixes postcss-preset-env @fullhuman/postcss-purgecss postcss

2a. (minimal setup) alter your postcss.config.js

module.exports = {
  plugins: {
      "postcss-flexbugs-fixes": {},
      "postcss-preset-env": {
          "autoprefixer": {
              "flexbox": "no-2009"
          },
          "stage": 3,
          "features": {
              "custom-properties": false
          }
      },
  },
}

2b. ( Our tailwind, storefront setup )

module.exports = {
  plugins: {
      tailwindcss: {},
      autoprefixer: {},
      "postcss-flexbugs-fixes": {},
      "postcss-preset-env": {
          "autoprefixer": {
              "flexbox": "no-2009"
          },
          "stage": 3,
          "features": {
              "custom-properties": false
          }
      },
      '@fullhuman/postcss-purgecss': {
          content: [
              './pages/**/*.{js,jsx,ts,tsx}',
              './components/**/*.{js,jsx,ts,tsx}',
              './lib/**/*.{js,jsx,ts,tsx}',
              './modules/**/*.{js,jsx,ts,tsx}'
          ],
          defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || [],
          safelist: ["html", "body"]
      }
  },
}
Collapse
 
karthikpamidimarri profile image
Karthik

Hi @thomasledoux1 ,
I have tried the same as per your blog it's working as expected but local css are not including

Collapse
 
vasujhawar profile image
Vasu Jhawar

By local css you mean inline style css/jsx or module.css?

Collapse
 
braydentw profile image
Brayden W ⚡️

Great tip! Can’t wait to try it.

Collapse
 
ravalika24 profile image
Ravalika24

I have tried these same steps on a next js application. But didn't see any difference in bundle size. Any help is much appreciated !

Collapse
 
trananhtuan400 profile image
evondev • Edited

I have an error when working with .scss, do you have any idea to fix this issue
dev-to-uploads.s3.amazonaws.com/up...

Collapse
 
thomasledoux1 profile image
Thomas Ledoux

Not really at first sight. I suggest asking on Stackoverflow with some code examples.