-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Integrate PurgeCSS directly into Tailwind #1639
Conversation
Please, don't forget add a example with prefix 😄 |
How about matching the regex you currently have AND the same thing without dots?
|
JSX uses “className” not “class” :) :class="{[someComputedValueThatReturnsAString]: true}" |
Thankfully not important for this.
Only if the computed value contains the entire class string and isn't dynamically calculated with weird string interpolation or anything. All of the regular limitations of PurgeCSS are unchanged here, read our guide on writing purgeable HTML: https://tailwindcss.com/docs/controlling-file-size/#writing-purgeable-html |
@utkarshkukreti Good idea! Updated it to support Pug a bit better using your solution 👍 |
@adamwathan Will this pass through whitelisting? |
haha this is great. I just added a little script on my forge deployments to do exactly this! |
Great improvement! Unfortunately, the @tailwind base;
@tailwind components;
/* purgecss start ignore */
@import "~toastr/toastr.scss";
@import "~@fancyapps/fancybox/dist/jquery.fancybox.css";
/* purgecss end ignore */
@tailwind utilities; But this still strips all of the css of toastr and fancybox. If you have a solution for this, that would be great 😃 Otherwise I guess it's still possible to pass |
Using ReactJS would mean add *.jsx or *.tsx to the list? Using VueJs would mean add *.vue to the list? No other changes required? |
Could this possibly be configurable? |
This is awesome 🤩 What’s the chances of you allowing to pass in a whitelist to ignore? I feel like many people use the whitelist... especially on CMS driven websites where classes might come from the database 😇 |
Anyone already trying this with Gatsby? Please, share your feedback if yes! |
Very nice feature! Thx! I did a quick test with your regex pattern and pug syntax and it turns out that following pug code does not properly support purging css class names:
Output of regex matching is following: As you can see, I had this issue already a few weeks ago and I came up with the solution to do the class extraction in multiple passes (following is postcss-purgecss config):
|
- Add better Pug support - Add "modes", with "all" and "conservative" by default - Allow passing options through to PurgeCSS - Rename `paths` to `content` to match PurgeCSS
@klaasgeldof The solution in your case is to use the preservable comment syntax for Sass: /** purgecss start ignore */ Note the double asterisk at the beginning 👍 Either way this issue won't impact this feature, these comments are added dynamically by Tailwind during the PostCSS phase, which is well after Sass is done looking at the files. |
@dominikzogg Correct, you just pass an array of paths to where all of your templates are and you're done (as long as you follow the rules of writing purgeable HTML). |
@adamwathan perfect |
I've pushed an update that makes things more configurable. Details below! Passing options directly to PurgeCSSNow you can pass an // tailwind.config.js
module.exports = {
purge: {
content: ['./src/**/*.html'],
// These options are passed directly to PurgeCSS
options: {
whitelist: ['bg-red-500', 'px-4']
}
},
// ...
} I've also renamed the Better Pug supportI've improved the matching strategy a bit more to better handle Pug. Works pretty great now, even on stuff like this: span.inline-grid.grid-cols-3(class="px-1.5")
.col-span-2
Hello
.col-span-1.text-center
World! New
|
This is huge. For folks (me) who accidentally purged things like the nprogress css styles and then are dumbfounded why the progress bar is not showing up, this will ease hours of frustration. |
is it will be |
@Haqverdi Only if you have actually provided a list of paths and |
This is awesome. Can't wait to use it! |
@adamwathan updated to 1.4 and adapted the config, works like a charm (react, vue) chubbyts/react-petstore@5c27bcb |
In my NextJS app, I have a |
Can you create a project that reproduces the issue so I can better help troubleshoot? |
@adamwathan Really sorry this was purely my fault. For some reason my tailwind was not updated to 1.4. Once i did it, everything worked as a charm. Thank you very much for adding this feature out of the box. BTW. the only issue which i face is, while using a custom variant, tailwind-dir where my |
Today i updated tailwind 1.4 to use purgecss. One thing i've noticed is that |
@divdax Had the same thing, this fixed it for me: purge: {
options: {
whitelistPatterns: [/^.[^\.]*\.[^\. "']*/],
},
}, @adamwathan Maybe include this pattern by default? |
It works! Thank you @klaasgeldof! 🙏 And yes... this pattern should be included by default. |
Not sure the framework should include white list patterns out of the box. That should probably be handled via an extractor pattern, like the one suggested by tailwindui. |
@divdax That class should not be purged using our default settings, we even have a test for that here: Can you create a project that reproduces the issue? |
I was wrong. Before Tailwind had purge baked in, the classes with dots were purged and I had to add the pattern. I copied my patterns (including this one) to the Tailwind purge config because I supposed it would behave the same. But now I removed the pattern and it works... @divdax Check if there is no other purging going on in your production build apart from the Tailwind purge. |
@adamwathan What do you mean with:
We still need to add some sort of tailwind.scss file and import it globally so all our components can use tailwind classes right? Would we copy the contents of your comment? Or could we just use:
and the right stuff is purged automatically without having to use /* purgecss start ignore */ comments? |
You don't have to copy the CSS I pasted there, it's just explaining how it's working conceptually to people who are used to configuring PurgeCSS with the ignore comments manually. |
Super cool to see this as part of the core! For those who want to combine this with Laravel (and possibly also for those migrating from module.exports = {
purge: {
// enabled: true,
content: [
"app/**/*.php",
"resources/**/*.html",
"resources/**/*.js",
"resources/**/*.jsx",
"resources/**/*.ts",
"resources/**/*.tsx",
"resources/**/*.php",
"resources/**/*.vue",
"resources/**/*.twig",
],
options: {
// defaultExtractor: (content) => content.match(/[\w-/.:]+(?<!:)/g) || [],
whitelistPatterns: [/-active$/, /-enter$/, /-leave-to$/, /show$/],
}
},
theme: {
extend: {},
},
variants: {},
plugins: [],
} If you want 100% the same exact behavior as Hope this helps! |
Very useful, thank you! |
I got it working fine on // tailwind.config.js
module.exports = {
prefix: 'tw-',
purge: {
content: [
'./components/**/*.vue',
'./layouts/**/*.vue',
'./pages/**/*.vue'
],
options: {
whitelist: ['antialiased', 'font-sans']
}
},
important: true,
theme: {},
variants: {},
plugins: []
} I noticed a little problem: I added the prefix "tw-" and when checking the generated css, I noticed that it had included ".tw-container" classes from Tailwind but I haven't used those at all. Thing is, Vuetify's got their own ".container" so it got ignored by the extractor even though I was using the prefix. Not a major problem but still unexpected result, I guess? BTW, thanks for this feature, I love it! |
This saved me two nights of shame. 😢 👍 |
This works great in a single app system. However in a CMS where you have lets say a User Front end and Admin section, how can you split the two css files. As an example
Is there a way to get the css for each page defined? eg. user.css and admin.css |
Do you have 2 css files output from the same tailwind config? Also, it's probably not recommended to use purge.enabled = true You should try use NODE_ENV as production and it's automatic then |
Thank you for the response, I think I figured out what I was looking to. In order to create a Laravel mix file for backend and frontend each (and other entry points if needed). For Laravel this is a must as it really makes not sense to have the css from frontend mixed with the backend. In reality what I will be working on is to make a css file for each page. This way you can take advantage of a super small css file in each page for use on something like AMP. I mean what is the point of using tailwindcss if we are not doing it all the way with Laravel :) package.json
webpack.mix.js:
create webpack.mix.website.js:
create webpack.mix.admin.js:
create tailwind.admin.config.js:
|
I have to point out, the above solution still does not fix the fundamental problem. As many know google will rate a website based on many aspects and one is Unused Css. So even if you run a purgecss and make the file smaller it will still have classes from other pages so you will still be penalized by google. In reality the solution would be to generate one css file per page each page on a website. However it is still better than other frameworks. |
@virgiltu do you have a source for your statement? |
Just use the google insight tool or lighthouse in dev tools. You will see google taking points for having unused CSS on the page. I am not sure how to add images but here is a list what you get penalized for. Eliminate render-blocking resources |
Hey! Looks like someone invited me to this issue. |
@givebk-bot !donate @adamwathan $1 thanks for this PR! |
🎁 Hey @adamwathan, you have just received U$ 1 from @nthypes!
@nthypes thanks for your support! ❤️
@adamwathan, you can check your balance at https://givebk.io.
═══
(powered by https://givebk.io)
ID: cd57e392-67c2-4dbc-b719-1975bb534e41
|
This PR adds a new
purge
config option for purging unused CSS directly from within Tailwind instead of having to pull in and configure PurgeCSS manually.The API is much more opinionated and slimmed down by default, optimizing for the 95% use case:
The
purge
option accepts an array of filenames/globs to scan for classes, and that's it. This should be enough for most people, but if you are one of those people who just can't help themselves and has to fiddle with everything, you can fine-tune the configuration however you like (keep reading for more on that).Things to note:
This option is only enabled when
NODE_ENV
isproduction
. If you want to enable it explicitly based on some other conditional logic, you can use an object syntax and theenabled
property, and specify your templates using thecontent
property:Only components and utilities are purged by default. Our base styles are not purged, and no custom CSS authored in your CSS files is purged, including any imports to outside libraries.
This is to make sure you don't accidentally run into common pitfalls, like forgetting to scan your root HTML template (which is difficult with frameworks like Next.js since it is buried in
node_modules
) or accidentally purging styles that come from whatever datepicker library you've pulled in as an npm dependency.This means we are not purging absolutely everything that could be safely purged, but you get 99% of the benefit with much less manual tuning. You will basically never need to whitelist anything using this approach.
Essentially we make your CSS file look like this:
If you really want to purge everything, you can do so using
mode: 'all'
:You're much more likely to accidentally remove important styles if you do this but I'm not the cops — if it tickles your pickle go for it.
We are using a new extractor strategy that tries to be as permissive as possible.
Here is the new extractor we're using:
...and here is the sample HTML we test our purging against:
It works really well and I would be pretty surprised if you ever needed to customize this.
If you want more control than what we offer, you can pass any options you want directly to PurgeCSS using the
options
property:Any options passed to PurgeCSS will override our own options, so for example if you pass
content
it will override ourcontent
property at the top-level.Happy purging 🤮