Developmint / nuxt-purgecss

Drop superfluous CSS! A neat PurgeCSS wrapper for Nuxt.js
MIT License
479 stars 19 forks source link

Dynamic classes are purged #14

Closed alexjoverm closed 5 years ago

alexjoverm commented 6 years ago

In components, you usually have classes added or generated dynamically:

<div :class="{ 'some-class': someCondition }">

Additionally, there are components not rendered in a first render, in particular those that don't meet the condition in a v-if directive.

For those, these dynamic classes are purged, breaking the styling of them.

A good solution can be what's mentioned in this issue about prefixing all Vue classes (for instance, with an underscore) and whitelist them.

Could we make that a default in this module? I think it could improve the DX, since the users don't need to worry about this or come across the same problem

alexjoverm commented 6 years ago

Double thinking about it, there is a downside: all the classes defined in Vue components won't be purged. Usually is in the global css where the are more classes not used, but it could happen in components as well.

What are your thoughts about this?

manniL commented 6 years ago

Hey @alexjoverm 👋

PurgeCSS does a string-based comparison approach. So <div :class="{ 'some-class': someCondition }"> should be detected (and not purged) properly.

However, classes live <div :class="'some-class-'+prop"> won't be recognized correctly.

Unfortunately, there is no ideal solution for that. As you said, prefixing all classes internally won't purge the unused CSS classes in global files which kills the benefits of PurgeCSS.

I've already included the defaults for body,html and the nuxt-* classes in the whitelist so people don't have to add them manually as well.

But in terms of "generated classes" adding them by hand might be the best option while still keeping all PurgeCSS benefits 🤔

alexjoverm commented 6 years ago

Hi @manniL :)

Yep, seems to be the case. I was even facing an issue where Google Maps were not displayed because one class used as a hook to inject GMaps was removed.

For me PurgeCSS seems like a trade-off: it indeeds provides a great value by potentially removing lots of CSS (specially in large legacy apps) with the risk of missing classes. I'd say a team must use it carefully, perfectly knowing the tool and making good use of it trying to dodge that risk.

But that's nothing related to this module. I think nuxt-purgecss is great and I was about to make it myself till I found it out. Good job!

It's cool to use this issue as a way to discuss a "good use" of purgecss :)

manniL commented 6 years ago

Yeah, I experienced that issue with GMaps as well in one of my current projects :see_no_evil:

As long as you think about adding classes to your whitelist when adding new modules to your app, you are good to go. And of course, tests in a production-like environment become more important with PurgeCSS.

Thanks a lot :pray: I'm happy you like the module! After using PurgeCSS as "plain implementation" (with build.extend) in more than a hand full of projects I was tired of always copy pasting the same code :D

Also, with this decoupling, the module itself gets more robust as testing is always present (and it'll check automatically against the new nuxt-edge releases, so it's future-proof as well). :raised_hands:

curtisbelt commented 5 years ago

@manniL PurgeCSS has whitelistPatterns which I make use of in my projects. I am just noticing it's absence in nuxt-purgecss as I was going to swap my vanilla implementation for this module.

https://github.com/FullHuman/purgecss-docs/blob/master/whitelisting.md

My build.extend:

extend(config, { isClient, isDev }) {
  config.plugins.push(
    new PurgecssPlugin({
      paths: glob.sync([
        path.join(__dirname, './pages/**/*.vue'),
        path.join(__dirname, './layouts/**/*.vue'),
        path.join(__dirname, './components/**/*.vue')
      ]),
      extractors: [
        {
          extractor: TailwindExtractor,
          extensions: ['html', 'js', 'vue']
        }
      ],
      whitelist: [
        'html',
        'body',
        'wf-active',
        'wf-inactive',
        'vue-map',
        'vue-map-container',
        'modal-open'
      ],
      whitelistPatterns: [/carousel\-/, /flickity\-/, /dynamic\-/, /noUi\-/]
    })
  );
}
manniL commented 5 years ago

Hey @CurtisBelt! I'm using whiteListPatterns in several of my projects and it works well with nuxt-purgecss. (example)

curtisbelt commented 5 years ago

@manniL Oh nice, thank you! I thought this issue would be solved by having whiteListPatterns but I understand now that I misread it.

manniL commented 5 years ago

Closing this for now :relaxed:

hjujah commented 4 years ago

Hmm... i can't make this to work. I want to whitelist all classes starting with d-, so for example d-md-block, d-lg-block etc... Please what am I doing wrong? Here is the relevant part of my nuxt config bellow... Thanks!

  buildModules: [
    ['nuxt-purgecss', {
      enabled: true
    }]
  ],

  purgeCSS: {
    mode: 'postcss',
    whitelistPatterns: [/d-$/]
  }
manniL commented 4 years ago

Hmm... i can't make this to work. I want to whitelist all classes starting with d-, so for example d-md-block, d-lg-block etc... Please what am I doing wrong? Here is the relevant part of my nuxt config bellow... Thanks!

  buildModules: [
    ['nuxt-purgecss', {
      enabled: true
    }]
  ],

  purgeCSS: {
    mode: 'postcss',
    whitelistPatterns: [/d-$/]
  }

You are mixing the "inline"-config with the purgeCSS config object. Use only one of them.