A discussão interminável sobre o pré-processador ideal para o CSS vem de muito tempo. Mesmo eu, que apesar de usar Sass em meus trabalhos, e apesar de ter criado um projeto open-source em cima disso, passei os últimos 2 anos advogando pelo Stylus. Agora mudei de ideia outra vez: vou usar PostCSS.
Por que não continuar com Sass?
O primeiro motivo sempre me foi claro: Sass não foi feito em JavaScript. E assim como disse Jeff Atwood:
“Tudo que puder ser escrito em JavaScript, será eventualmente escrito em JavaScript“.
E convenhamos: não dá pra discutir com quem tem página na WikiPedia. A verdade é que nenhuma linguagem se compara ao JavaScript quando o assunto é open-source e a participatividade da comunidade – pelo menos até agora.
Eu sei, o Sass agora tem o libsass e o node-sass. Quer dizer, então tudo ficou mais fácil: se você quiser contribuir você terá não só que entender de JavaScript, mas também de C++.
Por que nem Sass, nem LESS, nem Stylus?
Somente após ver uma alternativa – materializada na forma do PostCSS – é que eu entendi que meus maiores problemas com pré-processadores eram compartilhados por todos eles. E eu acho que eu devo uma explicação mais detalhada sobre alguns desses problemas.
Primeiro, a sintaxe
Pra quem não sabe, o primeiro a aparecer foi o Sass. Muito menos do que hoje, o que ele propunha na época era uma sintaxe nova – e mais simples – pra se escrever CSS. A sintaxe indentada simplificava o código, diminuía repetições através do aninhamento de seletores, e facilitava inclusive a adição de comentários.
Em seguida veio o LESS, com sua “sintaxe estendida”. Na prática, o que ele fazia era agregar possibilidades à sintaxe já existente, mas mantendo a compatibilidade com qualquer CSS que fosse inserido no seu código LESS. O Sass percebeu o valor disso, e criou uma nova sintaxe opcional; o SCSS.
Por último chegou o Stylus – que era uma cópia quase fiel às funcionalidades do Sass, mas que permitia um carnaval de sintaxes interoperantes. O grande trunfo do Stylus foi não ser o LESS, mas ainda assim ser escrito em JavaScript.
O problema? Uma vez que você opta por utilizá-los não haverá mais volta. Uma vez que você usa sua sintaxe, você dificilmente conseguirá portar seu código fonte para outra – ou mesmo para CSS puro, obviamente. Cada uma define seu próprio padrão, e por mais que, por exemplo, variáveis estejam quase chegando ao CSS, você sabe que no futuro seu código ainda não estará pronto para usá-las. No fim do dia você percebe que não está mais escrevendo CSS.
Não precisamentos nem recorrer à um futuro talvez distante; um exemplo clássico e atual são os mixins que você usa para entregar compatibilidade. Acredito que você não está mais no tempo de dar suporte ao IE8, mas até pouco tempo atrás eu me lembro de códigos mais ou menos assim:
div { @include opacity(0.5); }
Que seria então compilado para:
div { filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=50); opacity: 0.5; }
É fácil perceber que seu pré-processador acabou de ditar a sua sintaxe. Seu código não é mais seu. Seu código agora é dele.
Segundo, o excesso de funcionalidades
É claro que são justamente as funcionalidades que nos fazem recorrer aos pré-processadores. Eu não quero ficar sem variáveis, sem mixins, sem partials, etc e tal. Ocorre que justamente por entregar tantas funcionalidades e tão bem encaixotadas é que esses pré-processadores sofrem com manutenção do próprio ecossistema e com a falta de contribuidores.
Resolvi fazer uma pesquisa rápida para relacionar a quantidade de linhas de código e a quantidade de contribuidores desses projetos. Segue:
Linhas de código | Contribuidores | Média | |
Sass (Ruby) | 54915 | 176 | 312,01 |
Sass (node-sass + libsass) | 48668 | 202 | 240,93 |
Stylus | 46966 | 144 | 326,15 |
LESS | 42039 | 191 | 220,09 |
PostCSS | 13165 | 98 | 134,33 |
Vale esclarecer que essa análise é rasa, e que o significado que extraio aqui é praticamente uma opinião pessoal.
O que parece claro pra mim é que há uma relação inversa entre a quantidade de linhas de código – ou por consequência a complexidade ou a quantidade de funcionalidades embarcadas – à quantidade de contribuidores que compartilham responsabilidade sobre o projeto. Resumindo: quanto maior o code base menor é a quantidade de contribuidores, proporcionalmente.
A comunidade envolvida com Node definiu um padrão palpável na indústria de desenvolvimento: micro-módulos são a nova regra. Várias organizações e empresas já falaram sobre isso: Nodejitsu, Atlassian, e Nodesource, pra citar alguns. Os benefícios são vários, e o mais óbvio deles é também o menos técnico: você tem mais gente, cuidando de menos coisa.
O Sass é incrível. Suas funcionalidades são ótimas. Mas não só eu não preciso de todas elas, como eu preciso de outras que ele não tem. E não é simples assim adicionar alguma funcionalidade. Eu posso até criar ótimas funções customizadas, criar uma biblioteca de mixins, mas eu não posso mudar a forma como ele interpreta meu código.
O que é PostCSS?
Antes de mais nada, a informação mais importante que eu gostaria que vocês levassem deste artigo é: PostCSS não é uma alternativa aos pré-processadores.
PostCSS é um parser de CSS, capaz de criar uma árvore sintática abstrata e depois transformar isso em CSS novamente.
Complicado? Bom, vou dividir a explicação em quatro etapas de atuação:
A primeira etapa do PostCSS é receber seu código CSS e quebrá-lo em partes menores. Algo como ler seu CSS e processá-lo em “palavras”, ou tokens, sem significado individual: um espaço; uma chave; um número; e assim por diante. O processo é bem complicado, e falando técnicamente trata-se de uma análise léxica ou tokenização. Nesse momento são descartados caracteres sem utilidade, como espaços extra, indentação, ou quebras de linha.
A segunda etapa consiste do parser propriamente dito; um algoritmo capaz de processar o array de tokens e criar uma estrutura com significado. Por exemplo: um determinado conjunto de tokens se transforma em um seletor; outro se transforma no nome de uma propriedade. A partir daí é criada a árvore propriamente dita, relacionando valores à propriedades, propriedades à seletores, seletores à media queries, etc.
A terceira etapa é a parte divertida: a árvore criada no passo anterior é passada sequencialmente por uma lista de plugins, sofrendo alterações no caminho. Uma pipeline. Mais sobre isso à frente.
A quarta e última etapa é de responsabilidade do stringifier; um algoritmo que recebe a árvore modificada e a transforma novamente em CSS (ou qualquer outra coisa, mas isso não vem ao caso agora).
Sobre a etapa divertida. Ou: plugins.
O interessante até aqui é perceber que o PostCSS por si só não adiciona variáveis, mixins, partials, ou quaisquer dessas funcionalidades. E ele tampouco especifica uma nova sintaxe. Se algo aqui é uma alternativa aos pré-processadores que você já conhece, são os plugins. Sem o uso de plugins, PostCSS irá ler seu CSS e reescrevê-lo exatamente como ele o encontrou. Os plugins são os responsáveis por 100% das funcionalidades. E esse é o ponto mais importante desse novo ecossistema de processamento de CSS: a responsabilidade, a governança, e mesmo o código não estão centralizados em um único projeto.
O que um plugin pode fazer?
Tudo.
Ele pode adicionar variáveis. Ele pode permitir aninhamento de regras. Pode adicionar mixins. Pode garantir partials. Ou fazer tudo isso como o Sass faz. A lista de plugins cresce a cada momento, e criar um plugin é muito fácil. Talvez eu até fale sobre isso noutro momento.
Conclusão
Se Jeff Atwood escrevesse CSS, ele provavelmente diria que “Qualquer funcionalidade que puder ser desenvolvida usando PostCSS, será desenvolvida usando PostCSS”. Ok, eu estou exagerando um pouco. Mas a verdade é que o PostCSS invalida a briga pelo pré-processador ideal; ele nos prova que não precisamos disso. Não pode ser responsabilidade de uma única ferramenta resolver todos nossos problemas. E mais; nós também queremos fazer parte da solução dos nossos problemas, e a ferramenta ideal é justamente aquela que nos permite fazer isso, não uma que pretenda fazer tudo por nós.
No próximo artigo pretendo avançar mais em terrenos práticos, demonstrar formas de se utilizar PostCSS hoje, e como integrá-lo no seu sistema de build.
Até lá!