Por que usar o Sass
O CSS puro é suficiente para projetos pequenos, mas pode ficar repetitivo e difícil de organizar conforme a aplicação cresce. Cores, espaçamentos, breakpoints e regras de componentes acabam duplicados em vários arquivos, o que torna alterações simples mais trabalhosas do que deveriam.
Com o Sass, organizar seu projeto fica muito mais simples. Ele oferece recursos como variáveis e funções, tornando o código mais estruturado e reutilizável. Ao final, o Sass é convertido em CSS convencional, interpretado normalmente pelo navegador, enquanto o código-fonte permanece mais limpo, organizado e fácil de manter.
Outra grande vantagem na minha opnião, é você ter vários arquivos por módulo de seu sistema, e o output final ser um único arquivo minificado, sem a necessidade de declarar vários links de CSS no navegador.
$primary-color: #6750a4;
$spacing: 1rem;
.button {
padding: $spacing;
background: $primary-color;
&:hover {
opacity: 0.9;
}
}
A grande dor de devs que não são do ecossistema JS é criar e manter um pipeline separado apenas para compilar os arquivos .scss. Em muitos projetos, isso significa instalar o Node.js, arquivos de configuração e etapas específicas no CI/CD.
Por isso, criei a EmbeddedSass.Net, com a proposta de tornar a compilação Sass mais próxima das ferramentas que já fazem parte do desenvolvimento em .NET. Já existem diversas libs no mercado como a AspNetCore.SassCompiler, mas nenhuma até o momento que este artigo foi escrito, implementa o Embedded Sass Protocol.
O que é o EmbeddedSass.Net
O EmbeddedSass.Net é uma implementação em .NET do Embedded Sass Protocol.
O Embedded Sass Protocol define uma comunicação bidirecional entre o compilador Sass e uma linguagem hospedeira. O host solicita compilações ao Dart Sass e pode fornecer recursos como importadores, funções personalizadas e resolução de dependências.
Essa comunicação utiliza mensagens estruturadas, normalmente trocadas com o compilador executado como um processo separado. Dessa forma, o host consegue utilizar o compilador oficial sem precisar reimplementar a linguagem Sass.
Na prática, o EmbeddedSass.Net implementa esse protocolo para o ecossistema .NET, permitindo controlar a compilação Sass utilizando APIs e ferramentas familiares para desenvolvedores C#. Isso abre espaço tanto para integrações de build quanto para usos mais personalizados dentro de aplicações e ferramentas.
Neste link, é possível ver a especificação. Um detalhe muito interessante é que ela oferece um arquivo .proto que pode ser utilizado por qualquer linguagem para gerar os classes de comunicação.
Sass integrado ao MSBuild
Outra grande vantagem da minha biblioteca é o pacote EmbeddedSass.Net.MsBuild.
<ItemGroup>
<PackageReference Include="EmbeddedSass.Net.MsBuild"
PrivateAssets="all" />
</ItemGroup>
Esta lib compila os arquivos Sass antes de o ASP.NET Core processar os static web assets. Ele também inclui o compilador necessário, portanto não é preciso instalar o Sass separadamente na máquina de desenvolvimento ou no ambiente de build.
A compilação passa a fazer parte dos comandos normais do projeto:
dotnet build
dotnet publish
Com isso, no seu CI/CD não existe a necessidade de instalar nada do famoso Dependency Hell do npm. Para quem já utiliza MSBuild e os comandos do SDK do .NET, não há a necessidade de introduzir uma etapa adicional apenas para preparar os arquivos CSS.
Compilação em build-time
Por padrão, a biblioteca procura arquivos .scss e .sass dentro da pasta Sass. A ideia é oferecer uma configuração inicial simples, que funcione sem exigir diversas propriedades no projeto.
Sass/
├── _variables.scss
├── _buttons.scss
└── site.scss
Arquivos iniciados com _ são tratados como partials e não geram um arquivo CSS individual. Eles podem ser importados ou utilizados por outros arquivos Sass responsáveis por produzir a saída final.
O arquivo site.scss, por exemplo, é compilado para:
wwwroot/css/site.css
Em Debug, a integração gera CSS expandido e source maps, facilitando a leitura do resultado e a depuração no navegador. Nas demais configurações, como Release, gera CSS comprimido sem source maps por padrão, reduzindo o tamanho dos arquivos publicados.
Também é possível personalizar os diretórios de entrada, os caminhos de saída e os load paths diretamente no arquivo .csproj. Assim, a convenção padrão pode ser adaptada à estrutura já existente no projeto.
Compilação em runtime
O EmbeddedSass.Net também permite compilar Sass durante a execução da aplicação. Esse recurso é útil para gerar temas dinâmicos ou CSS baseado em configurações salvas no banco de dados.
using EmbeddedSass;
using EmbeddedSass.Compiler;
var options = new SassCompilerOptions()
.UseBundledDartSass();
await using var compiler = new SassCompiler(options);
var result = await compiler.CompileStringAsync("""
$primary-color: #6750a4;
.button {
background: $primary-color;
}
""");
Console.WriteLine(result.Css);
O CSS gerado fica disponível na propriedade Css e pode ser salvo em arquivo, armazenado em cache ou retornado diretamente por um endpoint.
Esse modo é indicado quando os estilos dependem de dados disponíveis apenas em runtime. Para arquivos estáticos, a integração com o MSBuild continua sendo a opção mais simples.
Benchmarks
Nos benchmarks realizados, o EmbeddedSass.Net apresentou um tempo de compilação 91,8% menor que o AspNetCore.SassCompiler e 98,9% menor que o DartSassHost, sendo aproximadamente 12 vezes e 87 vezes mais rápido respectivamente que as outras soluções do mercado.
Quando utilizar
O EmbeddedSass.Net.MsBuild é especialmente útil em projetos ASP.NET Core que servem arquivos estáticos diretamente.
Também é uma opção adequada para bibliotecas e aplicações que já dependem do SDK do .NET em seus ambientes de desenvolvimento e publicação. Um exemplo é o JJMasterData que utiliza o EmbeddedSass.Net para compilar seus estilos em um único arquivo jjmasterdata.css.
Conclusão
O código-fonte, a documentação e os exemplos estão disponíveis no GitHub, não esqueça de deixar sua estrela ⭐: