Skip to content
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

Reduce Tailwind CSS bundle size for unused components #877

Open
benjamincanac opened this issue Oct 27, 2023 — with Volta.net · 27 comments
Open

Reduce Tailwind CSS bundle size for unused components #877

benjamincanac opened this issue Oct 27, 2023 — with Volta.net · 27 comments
Labels
enhancement New feature or request help wanted Extra attention is needed v3 #1289

Comments

Copy link
Member

No description provided.

@benjamincanac benjamincanac added the enhancement New feature or request label Oct 27, 2023 — with Volta.net
@benjamincanac benjamincanac added the help wanted Extra attention is needed label Oct 27, 2023 — with Volta.net
@jrutila
Copy link
Sponsor Contributor

jrutila commented Oct 30, 2023

Related to #802 do you want separate issues on reducing the unused colors (this could be an option parameter, even) and reducing bundle size for unused components?

Copy link
Member Author

benjamincanac commented Oct 30, 2023

Removing unused colors is already done through Smart safelisting and I already answered here #802 (comment) on how to select only desired colors, not sure why you want to create another issue.

@jrutila
Copy link
Sponsor Contributor

jrutila commented Oct 30, 2023

I read the docs and that's what nuxt/ui is trying to achieve. But it doesn't seem to work as intended so I created a bug: #889. We can continue this color discussion there and leave the ticket for the unused component thing.

@ronenteva
Copy link

Sorry to jump in, but simply adding @nuxt/ui to an empty project creates an inline css of 243kb.
Is that related to this issue or something that I'm missing from the documentation?

Copy link
Member Author

It is related to this issue, the whole config is taken into account by Tailwind: https://github.com/nuxt/ui/blob/dev/src/runtime/ui.config.ts

@jrutila
Copy link
Sponsor Contributor

jrutila commented Nov 1, 2023

Is that ui.config file now available for Tailwind to do it's magic? Or does it do something more in nuxt/ui code? I am trying to scope the fix here.
If nuxt/ui would know which components the dev has used in the code it could cherry-pick those definitions from the config file for Tailwind, right?

@divine
Copy link

divine commented Nov 1, 2023

Hello,

This is pretty serious affecting performance.

@Atinux can this pushed forward please?

Thanks!

@raf202
Copy link

raf202 commented Nov 1, 2023

The build size is huge when using Static Site. Weirdly, NuxtUI is adding the tailwind styles inside a <style> tag inside all .HTML files. Is something broken or am I missing something?

@ronenteva
Copy link

@benjamincanac any timeline for this?
It's labeled as enhancement but I'm sure for many this issue is a deal-breaker for using @nuxt/ui

@ineshbose
Copy link
Member

Hey! We're researching into this and hoping to come up with a breakthrough soon. 😄

@jrutila
Copy link
Sponsor Contributor

jrutila commented Nov 7, 2023

The build size is huge when using Static Site. Weirdly, NuxtUI is adding the tailwind styles inside a <style> tag inside all .HTML files. Is something broken or am I missing something?

@sigmaxf I think this is more of nuxt's features. Try to fiddle with https://nuxt.com/docs/guide/going-further/experimental-features#inlinessrstyles

@ineshbose
Copy link
Member

There should be a workaround available for this now, if someone would like to report back on this please.

See "Tailwind CSS bundle" section on release notes for https://github.com/nuxt/ui/releases/tag/v2.11.0.

@ronenteva
Copy link

@ineshbose thanks! your help is highly appreciated!

I've tried excluding everything (on an empty project), and went down from 253kb to 185kb.
Big improvement but still huge for production.

Just to understand the issue, is it not possible to load nuxt ui before cssnano?

Here's what I excluded, if it helps anyone:

      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/data/table.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/accordion.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/alert.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/avatar.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/avatarGroup.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/badge.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/button.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/buttonGroup.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/chip.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/dropdown.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/kbd.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/meter.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/meterGroup.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/progress.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/forms/checkbox.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/forms/radioGroup.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/forms/radio.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/forms/toggle.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/forms/formGroup.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/forms/select.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/forms/textarea.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/forms/selectMenu.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/forms/range.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/forms/input.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/layout/card.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/layout/container.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/layout/divider.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/layout/skeleton.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/navigation/breadcrumb.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/navigation/commandPalette.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/navigation/pagination.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/navigation/verticalNavigation.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/overlays/contextMenu.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/overlays/modal.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/overlays/notification.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/overlays/notifications.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/overlays/popover.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/overlays/slideover.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/overlays/tooltip.mjs')

@jrutila
Copy link
Sponsor Contributor

jrutila commented Nov 24, 2023

@ronenteva have you limited the amount of color entries in the final outcome? It has an impact, too. See #889

@ronenteva
Copy link

@jrutila thanks! it's now down to 102kb

import colors from 'tailwindcss/colors';
import {resolve} from 'pathe';

export default {
  theme: {
    colors: {
      transparent: 'transparent',
      current: 'currentColor',
      black: colors.black,
      white: colors.white,
      gray: colors.gray,
      red: colors.red,
      green: colors.green
    }
  },
  content: {
    files: [
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/data/table.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/accordion.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/alert.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/avatar.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/avatarGroup.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/badge.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/button.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/buttonGroup.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/chip.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/dropdown.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/kbd.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/meter.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/meterGroup.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/elements/progress.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/forms/checkbox.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/forms/radioGroup.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/forms/radio.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/forms/toggle.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/forms/formGroup.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/forms/select.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/forms/textarea.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/forms/selectMenu.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/forms/range.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/forms/input.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/layout/card.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/layout/container.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/layout/divider.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/layout/skeleton.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/navigation/breadcrumb.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/navigation/commandPalette.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/navigation/pagination.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/navigation/verticalNavigation.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/overlays/contextMenu.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/overlays/modal.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/overlays/notification.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/overlays/notifications.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/overlays/popover.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/overlays/slideover.mjs'),
      '!' + resolve('node_modules/@nuxt/ui/dist/runtime/ui.config/overlays/tooltip.mjs')
    ]
  }
};

@ineshbose
Copy link
Member

Just to understand the issue, is it not possible to load nuxt ui before cssnano?

cssnano should include all the styles from NuxtUI after build.

@ineshbose
Copy link
Member

Let me add another solution to this problem: @nuxtjs/critters

This should remove unused styles from your page, but few things to note - load this module BEFORE @nuxt/ui, and it only works for generate/prerendered pages.

@ManasMadrecha
Copy link

@ineshbose Will the critters solution work for ssr:false and npm run generate project?

@ineshbose
Copy link
Member

Will the critters solution work for ssr:false and npm run generate project?

It needs SSR enabled. Rest, you can exclude files from Tailwind content (a for-loop or even a Nuxt module would be quite elegant) for now.

@champ7champ
Copy link

image How painful it is to look at this in 2024

@ronenteva
Copy link

@benjamincanac @ineshbose
I'm sorry to bump the issue but I want to make sure you guys understand that anyone who relies on SEO can't afford using @nuxt/ui until this is fully resolved.

@ineshbose
Copy link
Member

@ineshbose

I'm sorry to bump the issue but I want to make sure you guys understand that anyone who relies on SEO can't afford using @nuxt/ui until this is fully resolved.

Hey! Thanks for pinging - this issue is still in mind. Unfortunately content detection is a tricky part of Tailwind JIT and a component library based on Tailwind would have such limitations. We'll have to come up with some ground breaking stuff to have dynamic content based on import (contributions welcome) which all of TW community would benefit from, but till then we have a workaround available.

@ronenteva
Copy link

Let me add another solution to this problem: @nuxtjs/critters

This should remove unused styles from your page, but few things to note - load this module BEFORE @nuxt/ui, and it only works for generate/prerendered pages.

Do you mind sharing an example of how to use critters to remove the unused styles?
I couldn't get it to make any difference.

Another workaround is to use nuxt-purgecss and safelist all classes in the components in use.

Copy link
Member Author

@ronenteva Excluding all of the config files did not do the trick?

@ronenteva
Copy link

ronenteva commented Feb 27, 2024

@benjamincanac I stopped using it at some point but I honestly can't remember what wasn't working.
I'll give it another try and let you know.

Update:
I tested again, adding @nuxt/ui to a clean project and excluding all components, still adds 114kb of inline style.

@ronenteva
Copy link

If dark mode is not needed, you can save another 30k by setting:

nuxt.config.js

  colorMode: {
    preference: 'light'
  }

tailwind.config.js

  darkMode: []

@benjamincanac benjamincanac mentioned this issue Mar 4, 2024
8 tasks
@benjamincanac benjamincanac added the v3 #1289 label Mar 9, 2024
@yuzh2001
Copy link

Providing a workaround:

  1. first, build you app and launch it.
  2. curl http://localhost:3000 (for example)
  3. copy the longest <style>line starting as /* tailwind 4.3.1 ...
  4. save it to a seperate css file and upload it to cdn
  5. in nuxt.config.js/ts, set tailwindcss:{cssPath:false}, and in app:{head:{link:{... import the css on cdn

significantly drop from ~700kb to ~160kb

(the 160kb is because another ui library I use.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed v3 #1289
Projects
None yet
Development

No branches or pull requests

9 participants