Frontendowa magia: CoffeeScript, Sass, Scss, Less...

Tworząc kiedyś stronę internetową, trzeba było się nieźle napracować, by na każdym komputerze wyglądała mniej więcej tak samo. Każda przeglądarka interpretowała sobie kod po swojemu. Teraz jednak, gdy wszystkie nowe wersje popularnych przeglądarek trzymają się standardów (a nawet mój ulubiony były klient, Santander, przerzucił się z dinozaurów na aktualne wydania), no a zdecydowaną większość pozostałych jeszcze różnic między przeglądarkami można zniwelować używając normalize.css oraz jQuery, mogę z całą stanowczością uznać przenośność za największą zaletę technologii webowych. Piszesz kod raz, a działa wszędzie.

Z drugiej jednak strony tę samą przenośność można też uznać za wadę. Cały Internet sprowadza się bowiem ostatnio do tej świętej trójcy: HTML5 + CSS3 + JS. Bo skoro te trzy potrafią już wszystko to, co kiedyś umiały tylko Flash czy aplety Javy, to po co ryzykować bezpieczeństwo witryny, zmuszać użytkownika do instalowania wtyczek i odbierać sobie możliwość lepszej integracji elementów strony? Po prostu nie ma sensu wychodzić poza świętą trójcę. A jej rozwój jest niestety ograniczony aktualizacjami przeglądarek. Czy zatem jesteśmy na nią skazani?

Na szczęście nie! Istnieje cała rodzina języków, które bardzo sprytnie obchodzą ten problem. Wprowadzają ogromne ulepszenia i ułatwienia, ale bez potrzeby interpretowania ich przez przeglądarki! Po prostu po stronie programisty są kompilowane do jednego z tych języków, które każda przeglądarka rozumie.

Powiedzmy na przykład, że chcesz stworzyć w CSS klasy od col-1 do col-12, z których każda będzie nadawała DIV-owi szerokość równą ileśtam dwunastych szerokości kontenera. W Sass zajmuje to trzy linijki:

@for $i from 1 through 12
  .col-#{$i}
    width: $i/12 * 100%

A jest kompilowane do takiego kodu:

.col-1 {
  width: 8.33333%; }

.col-2 {
  width: 16.66667%; }

.col-3 {
  width: 25%; }

.col-4 {
  width: 33.33333%; }

.col-5 {
  width: 41.66667%; }

.col-6 {
  width: 50%; }

.col-7 {
  width: 58.33333%; }

.col-8 {
  width: 66.66667%; }

.col-9 {
  width: 75%; }

.col-10 {
  width: 83.33333%; }

.col-11 {
  width: 91.66667%; }

.col-12 {
  width: 100%; }

Pierwszy z nich jest prosty, krótki i czytelny dla człowieka, drugi natomiast zostanie zrozumiany przez wszystkie przeglądarki. I wilk syty i owca cała! Sass zawiera wiele elementów, których prostemu CSS-owi brakuje: zmiennych, instrukcji warunkowych, pętli, funkcji (tzw. mixins), zagnieżdżeń, operacji arytmetycznych... O ile bardziej elastyczny staje się kod, gdy możemy zdefiniować na przykład zmienną $navWidth: 300px i użyć jej w pięciu innych miejscach (również w wyrażeniach arytmetycznych, np. width: $navWidth / 2 + 16px), zamiast wszędzie podawać ją wprost. Każda zmiana szerokości nawigacji jest wtedy po prostu banalna, nie wymaga szukania wszystkich zależności. O ile krótszy i bardziej przejrzysty staje się kod, jeśli możemy często powtarzające się elementy zamknąć w parametryzowane mixiny i po prostu się do nich odwoływać? Świetną listę sassowych ficzerów można znaleźć choćby na Wikipedii.

Podobnymi do niego językami są Scss oras Less. Wolę jednak Sassa z jednego powodu – brak klamer. Skoro i tak w każdym kodzie powinno się stosować odpowiednie wcięcia tabulatorami, to klamry stają się zwyczajnie zbędne. Język, który wymusza stosowanie wcięć w kodzie po pierwsze wymaga mniej klepania w klawiaturę, a po drugie daje gwarancję, że po kim byśmy kodu nie przejęli, zawsze przynajmniej pod tym względem będzie on czytelny. Same plusy! Z tego samego założenia wyszli chociażby twórcy Rubiego, Pythona czy CoffeeScriptu.

A no właśnie, CoffeeScript. Żywy dowód, że nawet tworzenie JavaScriptów może być przyjemne (słowo daję, nie uwierzyłbym, gdybym nie spróbował). W JS to dopiero jest nadmiar nawiasów i klamer:

sse = new EventSource(Routing.generate('conversation_check'));
sse.addEventListener('conversation', function(e) {
  if (e.data == 'test' || e.data == 'dev') { return; }
  $.post(Routing.generate('conversation_fetch'), { ids: e.data }, function(data) {
    conversation.html(data);
  });
}, false);

Ta sama funkcjonalność w CoffeeScripcie wygląda następująco:

sse = new EventSource Routing.generate 'conversation_check'
sse.addEventListener 'conversation', (e) ->
  return if e.data in ['test', 'dev']
  $.post(Routing.generate('conversation_fetch'), { ids: e.data }, (data) ->
    conversation.html(data)
  )
, false

Wystarczyło zastąpienie składni function(a) {...} prostym (a) -> ..., zmiana klamer na wcięcia oraz możliwość pominięcia niektórych nawiasów w parametrach funkcji – i voilà! Mniej klepania w klawiaturę i doszukiwania się par nawiasów, a treści tyle samo!

Nie sposób się nachwalić wszystkich ficzerów CoffeeScriptu... JSON-owe obiekty można w nim definiować podobnie jak w YAML-u, pętlę można od 1 do 100 zawrzeć w króciutkim zapisie 1..100, zmiennych nie trzeba deklarować, można im przypisywać wartości do wielu na raz (a nawet zamieniać je wartościami w jednej linijce: [foo, bar] = [bar, foo] i tyle!). Najlepiej po prostu przejrzeć jego stronę domową i milczeć w zachwycie!

Również w przypadku HTML-a istnieje wiele technologii, które pozwalają na wygenerowanie go na postawie bardziej wyrafinowanych języków. Lecz tutaj to trochę co innego. Mowa o template engines takich jak Twig, Smarty, Haml czy Erb – one jednak są kompilowane do języków wykonywanych po stronie serwera (PHP, Ruby, Python...), więc niezbyt pasują do mojego zestawienia. (Nota bene w Hamlu jeszcze bardziej zredukowana jest klamrowa redundancja: z <html></html> robi się zwykłe %html)

Potrafię znaleźć tylko dwie wady całej tej rodziny technologii w porównaniu do świętej trójcy. Po pierwsze, tak jak przeglądarki, tak samo frontendowi programiści trójcę znają z całą pewnością, czego nie zawsze można powiedzieć o jej młodszym rodzeństwie. Więc jeśli ktoś dostanie po tobie projekt, w którym używałeś Sassa czy CoffeeScriptu, może nie być mu zbyt kolorowo. Z drugiej jednak strony, są to przecież technologie bardzo łatwe do przyswojenia, a zarazem niezmiernie przydatne i wygodne. Więc chyba tylko wyświadczyłbyś mu przysługę, prawda?

Po drugie natomiast, kompilowanie trwa i wymaga zachodu. Wystarczy jednak zainstalować Bowera albo skonfigurować sobie watchera w PhpStormie, aby każde zapisanie pliku automatycznie uruchamiało kompilację. Naprawdę, wygodniej już się tego zrobić nie da!

A poza tym same plusy. Jeśli tworzysz strony, a jeszcze nie znasz tych technologii – koniecznie je wypróbuj! Z odrobiną wprawy i doświadczenia, połowa twoich frontendowych problemów może zniknąć.

A photo of me

About the author

Hi! I'm Andrea (they/them). I tell computers what to do, both for a living and for fun, I'm also into blogging, writing and photography. I'm trying to make the world just a little bit better: more inclusive, more rational and more just.