mangle-css-class-webpack-plugin icon indicating copy to clipboard operation
mangle-css-class-webpack-plugin copied to clipboard

Double generation of CSS class names (Next.JS + Tailwind)

Open gggglglglg opened this issue 3 years ago • 3 comments

Hi I use Tailwind with the prefix tw-

In next.config.js:

reactStrictMode: false,
...
 if (!dev) {
      const MangleCssClassPlugin = require('mangle-css-class-webpack-plugin')

      config.plugins.push(
          new MangleCssClassPlugin({
            classNameRegExp: '((hover|focus|active|disabled|visited|first|last|odd|even|group-hover|focus-within|xs|sm|md|lg|xl)[\\\\]*:)*tw-[a-zA-Z0-9_-]*([\\\\]*\/[0-9]*)?',
            ignorePrefixRegExp: '((hover|focus|active|disabled|visited|first|last|odd|even|group-hover|focus-within|xs|sm|md||lg|xl)[\\\\]*:)*',
            log: true,

            })
        )
    }

When I run a build, the css file gets double class names (check tw-py-8)

Minify class name from tw-font-body to d
Minify class name from tw-py-8 to e
Skip the prefix md: of md:tw-py-12
Minify class name from tw-py-12 to f
...
Minify class name from tw-py-8 to ya

As we see the tw-py-8 class is processed twice (E and YA) So the css file looks like this (for tw-py-8):

.e {
 left:50%
}
.ya {
 padding-top:2rem;
 padding-bottom:2rem
}

As we see the YA class is correct (for tailwind tw-py-8) BUT The class E is inserted in the page

As a result, the entire design does not display correctly

Any idea?

PS: Next.js last version Tailwind last version

gggglglglg avatar Sep 08 '22 16:09 gggglglglg

It seems the problem is the server side rendering vs client side rendering. Fix would be a custom classGenerator.

aNNdii avatar Sep 16 '22 22:09 aNNdii

i tried this

// next.config.js
webpack(config, { dev, nextRuntime }) {
  ...
  console.log('webpack ran, nextRuntime :', nextRuntime )
  ...
}

and it ran 3 times, which is probably the problem. one for edge, nodejs, and undefined (client). i tried some different scenarios so webpack only ran once. i checked the

and went to the autogenerated css

client

// next.config.js
...
if (!dev && typeof nextRuntime === 'undefined') {
  config.plugins.push(
    new MangleCssClassPlugin({
      // settings
    )}
  )
}

only the autogenerated css file classnames changed, but not the html classnames then i tried with nodejs

// next.config.js
...
if (!dev && nextRuntime === 'nodejs') {
  config.plugins.push(
    new MangleCssClassPlugin({
      // settings
    )}
  )
}

only the html classnames and not the autogenerated css file classnames i think the problem is that the different runtimes generate different classnames but we need both because one generates the html classnames and one is required to generate the css file classnames best solution would be for a custom classgenerator so the client and server have consistent classnames

try something like

classGenerator: original => btoa(original).replace(/=/g, '')

this will ensure the classnames are consistent and unqiue and removes the equal signs which break the css

hope this helpful

frog1123 avatar Sep 23 '22 22:09 frog1123

@ermaxinc @frog1123 Release the new version(5.0.9) which may fix the issue. Could you check if it works?

Here it makes the ClassGenerator Instance singleton. https://github.com/sndyuk/mangle-css-class-webpack-plugin/commit/3eeffcefe817eafd321ab545f25c004b796962cb#diff-cd079ac25597bb2b0b25c925d8be0ad595d5aaacea6b023c3df55e5795c87b3cR87

sndyuk avatar Oct 11 '22 12:10 sndyuk