Esse foi até um dos casos extremos que resolvi recentemente (cada coisa que chega para mim resolver 😅). Percebo, por esse caso, que o maior problema é que o Tailwind não otimizou a produção de CSS para medias queries (breakpoints), além disso, quando falamos de otimização temos (1) CSS crítico e (2) CSS regular. Aí varia do que cada um vai fazer. No caso desse que otimizei foi: (1) breakpoints em excesso, (2) classes usadas uma única vez sem padronização, (3) uso excessivo de palheta de cores e (4) uso de utilitários como @tailwindcss/typography
.
Outro ponto que acho horrível no Tailwind, por exemplo, é a incapacidade de quebrar o bundle em dois ou mais fragmentos. Ele simplemente vai pegar todas as classes utilizadas na aplicação e agrupar tudo. Aí quando você tem um desenvolvedor inexperiente ou, pior ainda, componentes com uma porrada de classe é fácil as coisas sairem do controle.
Além disso, muitos frameworks agrupam o font-face com o CSS do Tailwind produzindo um bundle ainda maior que vai ter que ser carregado pelo browser e processado antes de mostrar ao usuário.
Quando o foco é performance não uso Tailwind ou faço um misto. Gosto da ferramenta, ela facilita muito o trabalho. Geralmente utilizo ela para um mock e depois depois saio convertendo os estilos para classes normais do CSS para montar um bundle de CSS crítico. Assim separo o que é crítico do que pode ser processado depois. Aí vai da experiência de cada um.
O dia que o Tailwind resolver totalmente a questão de separação de bundles vou usar ele por completo.