Rails-Anwendungen auf LibSass umstellen

Seit April 2018 ist Ruby-Sass offiziell deprecated. Damit ist auch das Sass-Gem betroffen, welches Rails-Anwendungen standardmäßig verwenden.

Die Entwickler von Sass empfehlen eine Umstellung auf die LibSass-Alternative. Dies haben wir in einem umfangreichen Projekt getan und uns dabei einigen Hürden erfolgreich gestellt.

Warum Sass?

Beim Entwickeln und Pflegen von CSS sind Präprozessoren wie Sass eine große Erleichterung, doch im Gegensatz zu reinem Vanilla CSS muss Sass das CSS erst kompilieren.

Rails-Anwendungen ab Version 3.1 werden bei der Erstellung automatisch mit dem Gem sass-rails ausgestattet, welches die Standard Sass-Engine verwendet, die in Ruby geschrieben wurde.

Diese Ruby-Sass-Engine ist nun deprecated und sollte daher zeitnah ersetzt werden. Bis Frühjahr 2019 werden noch Bugfixes und wichtige Updates für Ruby Sass vorgenommen, danach wird das Projekt vollständig eingestellt. Feature-Updates werden schon jetzt nicht mehr ausgeliefert.

Grund für diesen Schritt ist das Release von DartSass, welches ab sofort die neue Hauptimplementierung von Sass sein soll. Alle neuen Features werden zuerst für DartSass veröffentlicht.

Als Entwickler im Ruby-Umfeld steht man aber vor dem Problem, dass es für DartSass noch keine Ruby-Integration gibt. Es gibt bereits ein Issue dafür, früher oder später wird dies also nachgeholt werden. In der Zwischenzeit empfehlen die Sass Maintainer aber LibSass als Alternative, eine in C/C++ portierte Version der Sass-Engine, welche es schon eine Weile gibt und welche auch weiterhin Feature-Updates erhält (wenn auch mit zeitlicher Verzögerung zu DartSass).

Bei der Entwicklung von LibSass wurde ganz bewusst auf die Effizienz geachtet. Mit LibSass geht damit auch das Kompilieren deutlich schneller als mit Ruby-Sass, ein weiterer Vorteil bei einer Umstellung! Durch einige weitere Optimierungen kann man sogar mit einer Reduzierung der Dateigröße des erzeugten Stylesheets rechnen.

Für Rails-Projekte gibt es das Gem sassc-rails („SassC“), welches LibSass implementiert.

In neuen Rails-Projekten das alte Standard-Gem durch SassC zu ersetzen, ist keine große Kunst, doch wie sieht es mit bestehenden Projekten aus, welche Hürden könnten dafür bestehen?

Wir haben eine große historisch gewachsene Rails-Anwendung auf LibSass umgestellt und konnten einige Erfahrungen damit machen.

Von sass-rails zu sassc-rails — die Umstellung in der Praxis

Sass Funktions-Erweiterungen

Interessant wird die Umstellung vor allem dann, wenn im Projekt noch weitere Gems verwendet werden, die sich auf Sass stützen und es erweitern. Wie es das Schicksal wollte, hatten wir diesen Fall:

sass-rails-images ist ein nützlicher Helfer, mit dem man zum Beispiel innerhalb von CSS die Höhe und Breite von Bildern abfragen kann, ähnlich wie dies auch mit dem „Compass“ Sass-Framework möglich ist. Dazu erweitert das Gem Sass um zwei weitere Funktionen, welche die Höhe bzw. Breite von Bildern in Pixeln zurückgeben.

Nach der Umstellung auf SassC hat man mit Gems dieser Art ein Problem: Die gepatchten Funktionen beziehen sich ganz konkret auf Sass-Module und greifen daher nicht mehr. Um die Funktionalität in SassC wiederherzustellen, muss der Modulname zu SassC geändert werden.

Idealerweise handelt es sich um ein Gem, für das es auch schon eine SassC-Implementierung gibt. Dann wurde einem die Arbeit bereits abgenommen und man muss nur das Gem austauschen. Ist dies nicht der Fall und kann man auf das Gem nicht verzichten, kann man die Anpassung des Modulnamens selbst per Hand in der config/initializers/sprockets.rb vornehmen.

module SassC
  module Script
    module Functions
      def custom_sassc_function
        ...

Compass

Ein weiteres Problem bei der Umstellung auf LibSass könnte auch das bereits erwähnte und ehemals weit verbreitete Sass-Framework „Compass“ sein. Dieses ist in Ruby-Sass geschrieben und nicht mit LibSass kompatibel.

Gemäß dem Hinweis auf der GitHub-Seite wird Compass seit zwei Jahren schon nicht mehr gewartet, nichtsdestotrotz ist es sehr wahrscheinlich, dass viele alte Projekte, die noch mit Ruby-Sass laufen auch noch Compass verwenden.

Für eine Umstellung muss die Fülle an nützlichen verwendeten Features, die Compass zur Verfügung stellt, ersetzt werden. Diese sind mit hoher Wahrscheinlichkeit:

1. Mixins und Funktionen

Diese lassen sich relativ problemlos nachbauen, wenn auch je nach verwendeten Mixins mit etwas Aufwand verbunden. Diesen Weg sind wir in unserem Projekt gegangen.

Viele der Mixins, welche Compass zur Verfügung stellt, dienen dem Zweck, Vendor-Präfixe vor einige CSS-Eigenschaften wie zum Beispiel border-radius zu stellen. Anstelle dies weiterhin über Mixins zu regeln, bietet sich inzwischen auch der CSS Postprozessor Autoprefixer an, welcher sich das von Sass fertig kompilierte CSS nochmal vornimmt und alle nötigen Eigenschaften (frei konfigurierbar) mit Vendor-Präfixen versieht.

2. Spritesheets

Automatisch generierte Spritesheets aus einer Reihe von PNG-Dateien inklusive Sass-Funktionen zum Auslesen von Größe und Position jedes Sprites sind eine der größten Stärken von Compass. Diese Funktion nahtlos zu ersetzen stellt etwas mehr Aufwand dar. Sofern man nicht komplett darauf verzichten kann und die Funktion nicht händisch nachbauen möchte, könnte eine mögliche Alternative zum Beispiel Sprite Factory sein.

Nette Nebeneffekte nach der Umstellung — Performance

Selbst, wenn Ruby-Sass nicht deprecated wäre, wäre eine Umstellung auf LibSass empfehlenswert. Folgende nette Nebeneffekte konnten wir nach unserer Umstellung verzeichen:

Die Seiten-Ladezeit nach CSS-Änderungen ist in unserem Entwicklungsmodus um satte 89 % gesunken. Zusätzlich sind auch unsere Stylesheets im Schnitt 6 % kleiner geworden (unkomprimiert) — ein Vorteil, von dem am Ende auch die Nutzer profitieren, nicht nur die Entwickler.