prvnbist
prvnbist

Reputation: 451

Why are css classes are missing in production when using Tailwind and next.js?

Tailwind version: v9.3.5

PostCSS Config:

// postcss.config.js

module.exports = {
   plugins: {
      tailwindcss: {},
      autoprefixer: {},
      ...(process.env.NODE_ENV === 'production'
         ? {
              '@fullhuman/postcss-purgecss': {
                 content: ['./components/**/*.js', './pages/**/*.js'],
                 defaultExtractor: content =>
                    content.match(/[\w-/:]+(?<!:)/g) || [],
              },
           }
         : {}),
   },
}

Tailwind Config:

// tailwind.config.js

module.exports = {
   theme: {
      extend: {
         colors: {
            tint: 'rgba(0,0,0,0.3)',
         },
      },
   },
   variants: {},
   plugins: [],
}

Styles work perfectly in development but in production only some styling is working. Upon checking the CSS file in build folder, looks like some of the CSS classes are not being extracted or possibly purged therefore resulting in partial styling of the app.

Upvotes: 11

Views: 10626

Answers (3)

Dominic Marrone
Dominic Marrone

Reputation: 61

I struggled with this same issue. Tailwind will purge classes created with string concatenation.

One solve is to save class names as variables.

n = ‘row-start-2’;

className={n}

For my use case I couldn't do this. Instead, I used the safelist greedy option.

In tailwind config file:


module.exports = {
  purge: {
    content: ["./pages/**/*.{js,ts,jsx,tsx}", "./components/**/*.{js,ts,jsx,tsx}"],
    options: {
      safelist: {
        greedy: ["/safe$/"],
      },
    },
  },

Then I added the "safe" class to all elements where I'm using string concatenation to create classes.

className={`safe sm:grid-cols-${smCols} sm:grid-rows-${smRows} md:grid-cols-${mdCols} md:grid-rows-${mdRows}

Upvotes: 0

BENMEDDAH Mohamed
BENMEDDAH Mohamed

Reputation: 221

EDIT : PurgeCSS version 3.0 add safelist option, replace whitelist

I faced the same problem when i dynamically inject name of some classes into my html template.
I am using nuxt.js/tailwindcss so you need to read the documentary first to solve your problem.

Problem

here's the code who generate the classes missing in production

 computed: {
    axeY() {
      return this.y < 0 ? `-translate-y${this.y}` + ' ' : `translate-y-1` + ' '
    },
    axeX() {
      return this.x < 0 ? `-translate-x${this.x}` : `translate-x-${this.x}`
    },

PostCSS will analyse all files into the content table (declaring in the config file),
noted that my files doesn't include classes with translate prefix
as you can see, my missing classes are: [translate-x-1,-translate-x-1, translate-y-1, -translate-y-1] ... the number 1 is a variable.

Solution

  • I need to tell purgecss to not delete those classes by adding them into a whitelist
  • Or you can use them into your files, for example by creating an unless file (a file analyzed by PostCSS)

You can specify content that should be analyzed by PurgeCSS with an array of filenames

  • Maintain your config file of TailWindCSS by specifying all cores plugins that you're using
  • In a complicated case you can use a regular expression in the config file.
    in my case, i can directly config purge in the config file of TailWindCSS, by passing the whitelist in the options variable,
    and here is my config file when i use the first solution :
/*
 ** TailwindCSS Configuration File
 **
 ** Docs: https://tailwindcss.com/docs/configuration
 ** Default: https://github.com/tailwindcss/tailwindcss/blob/master/stubs/defaultConfig.stub.js
 */
const num = [1, 2, 3, 4, 5, 6, 8, 10, 12]
const whitelist = []
num.map((x) => {
  whitelist.push('translate-x-' + x)
  whitelist.push('-translate-x-' + x)
  whitelist.push('translate-y-' + x)
  whitelist.push('-translate-y-' + x)
})
module.exports = {
  future: {
    removeDeprecatedGapUtilities: true,
  },
  theme: {},
  variants: {
    backgroundColor: ['hover', 'focus', 'active'],
  },
  plugins: [],
  purge: {
    // Learn more on https://tailwindcss.com/docs/controlling-file-size/#removing-unused-css
    enabled: process.env.NODE_ENV === 'production',
    content: [
      'components/**/*.vue',
      'layouts/**/*.vue',
      'pages/**/*.vue',
      'plugins/**/*.js',
      'nuxt.config.js',
    ],
    options: {
      whitelist,
    },
  },
}

Upvotes: 9

prvnbist
prvnbist

Reputation: 451

Found the issue, postcss config was missing sections folder in content array and also since my js files had jsx, i need to add that as well.

// postcss.config.js

module.exports = {
   plugins: {
      tailwindcss: {},
      autoprefixer: {},
      ...(process.env.NODE_ENV === 'production'
         ? {
              '@fullhuman/postcss-purgecss': {
                 // added sections folder and changed extension to jsx
                 content: ['./components/**/*.jsx', './pages/**/*.js', './sections/**/**/*.jsx'],
                 defaultExtractor: content =>
                    content.match(/[\w-/:]+(?<!:)/g) || [],
              },
           }
         : {}),
   },
}

Upvotes: 4

Related Questions