Warsztat leniwego programisty – wprowadzenie do Yeoman, Grunt i Bower

Artykuł jest zapisem prezentacji wygłoszonej na meetjs – spotkaniu śląskich programistów JavaScript, której tematem było wprowadzenie do Grunt, Bower i Yeoman oraz jak zautomatyzować niektóre codzienne zadania, które musi wykonywać webdeveloper.

Dlaczego programista powinien być leniwy?

Zanim wytłumaczę, dlaczego programiści powinni być leniwi, wytłumaczę, o jakie dokładnie lenistwo mi chodzi. Nie mam na myśli lenistwa w stylu „nie chce mi się wstać z łóżka” czy „nie chce mi się, zrobię jutro”. Mam na myśli lenistwo, które zmusza nas do automatyzacji pracy. Lenistwo, którego paradoksalnym rezultatem jest większa efektywność pracy.

Często trafiają nam się żmudne, powtarzalne lub nudne zadania. Kompilacja styli z LESS/SASS do CSS czy tworzenie zminimalizowanej wersji naszych skryptów JS – to są przykłady takich zadań. Coś zmieniamy, wchodzimy do konsoli, odpalamy jakieś komendy, czekamy i sprawdzamy, czy wszystko jest w porządku. Od zmiany do weryfikacji zmiany musimy zrobić co najmniej trzy dodatkowe kroki. Marnujemy czas na niepotrzebne kroki, które można za pomocą odpowiednio ustawionych skryptów wyrzucić z naszego workflow. Albo na szukanie, ściąganie i rozpakowywanie potrzebnej nam biblioteki. Albo na postawienie nowego projektu lub jego części. We wszystkich tych przypadkach możemy zaoszczędzić trochę czasu, a pomogą nam w tym Grunt, Bower i Yeoman.

Zerknijcie na poniższy wykres. Pokazuje jak geek i nie-geek podchodzą do powtarzalnych tasków (zakładam, że każdy programista jest w większym bądź mniejszym stopniu geekiem). W pewnym momencie geek/programista osiąga taki punkt, w którym dla niego bardziej opłaca się poświęcić więcej czasu na napisanie odpowiednich skryptów i zautomatyzować pracę niż brnąć w ręczne wykonywanie pojedynczych poleceń.

lazy-graph

Skupię się w tym artykule na pionowej linii pomiędzy punktem „wkurzenia się”, a Punktem „w którym odpala się skrypt” oraz jak zautomatyzować pracę używając tylko JavaScript.

Grunt, czyli task runner w JS

grunt

Podstawowym narzędziem, który pozwoli nam zautomatyzować nasz workflow jest Grunt. Grunt jest task runnerem, w którym taski opisujemy za pomocą JS. Jest to potężne narzędzie, które odpowiednio skonfigurowane potrafi znacząco ułatwić nam życie.

Instalacja Grunt jest bardzo prosta. Projekt w Gruncie składa się z dwóch plików: package.json i Gruntfile.js. Pliki te możemy albo wygenerować korzystając z grunt-init (po zainstalowaniu odpowiednich szablonów) albo utworzyć samemu.

package.json jest plikiem wykorzystywanym przez npm i zawiera opis naszego projektu oraz listę modułów node’a, które będą nam potrzebne. package.json powinien się znajdować w tym samym katalogu co plik Gruntfile.js. Szczegółowy opis z czego składa się ten plik znajdziecie na oficjalnej stronie npm lub na stronie nodejitsu. Po skonfigurowaniu package.json instalujemy potrzebne moduły komendą (w zależności od konfiguracji systemu uruchamiamy polecenia instalujące cokolwiek poprzez npm z sudo lub bez): npm install.

W tym momencie zostaną ściągnięte wybrane moduły wraz z zależnościami i zostaną one zapisane w katalogu node_modules, znajdującym się w tym samym katalogu co package.json.

Mając już potrzebne moduły pora przygotować skrypty. Do tego służy plik Gruntfile.js (lub Gruntfile.coffee). To w nim opisujemy jakie są nasze taski.

Najlepiej przedstawić działanie Grunta na przykładzie prostej strony (która jest dostępna na GitHub), gdzie pokażę, ile pracy można zautomatyzować przy pomocy Grunt.

Naszym pierwszym taskiem będzie kompilacja plików LESS do CSS. Najpierw musimy znaleźć odpowiedni moduł do tego. Przyda się tutaj lista modułów na stronie Grunta. Lista dostępnych modułów jest ogromna – obecnie znajduje się w niej prawie 1850 pozycji. W wielu przypadkach moduły, które można doładować do Grunta są w stanie wykonać prawie wszystkie zadania, jakie mogą nam się przytrafić. Są moduły kompilujące LESS czy SASS do CSS, moduły do testowania kodu (Karma, Moccha, itp.), moduły do kompilacji szablonów (np. JST, Handlebars), do generowania dokumentacji, optymalizacji obrazków, minimalizowania kodu JS i CSS, kopiowania plików, czyszczenia folderów. Jest tego cała masa. Gdyby jednak okazało się, że potrzebujemy specyficzny task to zawsze możemy sami taki napisać. Dokładny opis jak to się robi znajdziecie na stronie Grunta.

Znajdujemy grunt-contrib-less, klikamy w link i pokazuje nam się strona z opisem instalacji. Instalujemy moduł: npm install grunt-contrib-less --save-dev.

Ustawienie --save-dev sprawia, że instalowany moduł zostanie zapisany w pliku package.json w sekcji devDependencies. Jeżeli nie podamy ani --save-dev ani --save (które zapisuje do sekcji dependencies) to moduł zostanie zainstalowany, lecz nie zostanie zapisany w package.json.

Następnym krokiem jest załadowanie modułu do Grunta i napisanie taska. Załadujmy go więc pisząc:
grunt.loadNpmTasks('grunt-contrib-less');
Od tej pory możemy korzystać z modułu do kompilacji plików LESS w Grunt. Sam task wygląda natomiast następująco:

Mamy tutaj konfigurację tasku less (dokładniejsze informacje co do czego służy znajdziecie tutaj), który składa się z dwóch wariantów – development i production. Taski w Grunt mogą mieć swoje warianty różniące się konfiguracją.

Dobra, pora odpalić task! Wpisujemy w konsoli: grunt less:development.
Właśnie Grunt odpalił swój pierwszy task. Dokładniej mówiąc odpalił task less w wariancie development. Gdybyśmy nie podali o jaki wariant nam chodzi Grunt odpaliłby po kolei wszystkie warianty.

„Ładnie”, ktoś może powiedzieć, „zastąpiłeś jedną komendę drugą i nic nie zyskałem poza tym, że teraz wszystko mam w Gruncie”. Ok. Możemy w Gruncie ustawić skrypt nasłuchujący na zmiany na określonych plikach i odpalający konkretną akcję na ich zmianie. Pozbędziemy się dzięki temu kroku ręcznej kompilacji plików LESS. Do dzieła!

Moduł, który nas interesuje nazywa się grunt-contrib-watch. Instalujemy go:
npm install grunt-contrib-watch --save-dev

Ładujemy:
grunt.loadNpmTasks('grunt-contrib-watch');

I konfigurujemy:

Ustawiliśmy watch tak, aby obserwował zmiany na plikach less w katalogu less/. Jeżeli zauważy jakąś zmianę ma odpalić task less:development. Dobrym pomysłem byłoby teraz otwarcie kolejnego okna konsoli i odpalenie w nim: grunt watch.
Teraz zmieńmy coś w plikach less i bez wchodzenia do konsoli odświeżmy stronę. Voila! Jeden krok mniej! Pójdźmy jeszcze dalej. Sprawimy, że po zmianie czegokolwiek w plikach less i HTML przeglądarka sama nam się odświeży. Takie rzeczy także można zrobić w Gruncie. Zmieńmy nieco task watch:

Dodajmy również do index.html, tuż przed </body>:
<script src="//localhost:35729/livereload.js"></script>

Zatrzymajmy poprzedni task grunt watch i odpalmy go ponownie oraz odświeżmy stronę. Od tej pory jakiekolwiek zmiany w plikach less i HTML spowodują natychmiastowe przeładowanie strony. Pozbyliśmy się w ten sposób jeszcze jednego kroku – nie musimy ręcznie odświeżać strony po zmianach. Jest to bardzo przydatne, gdy pracujemy na dwóch ekranach i na jednym edytujemy kod, a na drugim mamy naszą stronę. Nie musimy się przełączać między oknami i odświeżać strony ręcznie. Wszystko robi za nas Grunt.

Pojedyncze taski można łączyć w większe taski. Przykładowo task zajmujący się przygotowaniem wersji produkcyjnej naszego projektu może sprawdzić poprawność składni JSHintem, potem odpalić testy jednostkowe, skompilować style i wygenerować dokumentację. Takie zgrupowane taski można zastąpić jednym taskiem, np.:

grunt.registerTask('dist', ['concat:dist', 'uglify:dist']);

Od tej pory odpalając grunt dist tak naprawdę będziemy odpalać dwa taski – concat:dist, a zaraz po nim uglify:dist. Możemy również zdefiniować domyślny zestaw tasków odpalanych, gdy wpiszemy tylko grunt.

grunt.registerTask('default', ['uglify'])

Bower, czyli package manager for the web

bower

Bower to front-end package management. Oznacza to, że jego zadaniem jest zarządzanie wszystkimi bibliotekami, które mamy zamiar wykorzystywać w przeglądarce.

Korzystanie z Bowera również jest proste. Spróbujmy dodać do naszego projektu jQuery. Możemy skorzystać z konsolowej wyszukiwarki wpisując bower search jquery lub skorzystać z odpowiedniej strony. W chwili, gdy to piszę Bower posiada ponad 6000 bibliotek. Istnieje więc duża szansa, że biblioteka, której szukasz można znaleźć w Bowerze.

Gdy już znaleźliśmy naszą bibliotekę pora ją zainstalować bower install jquery.
Ważna uwaga – nie wolno poprzedzić tej instrukcji komendą sudo! Jest to bardzo głupie. Tak głupie, że Bower nawet grzecznie się zapyta, czy na pewno ma kontynuować.

Możemy dopisać --save, aby informacja o dokładnej wersji zapisała się w pliku bower.json. W tym momencie Bower ściągnie nam najnowszą wersję jQuery do odpowiedniego katalogu (domyślnie jest nim bower_components). Nie musimy od tej pory wchodzić na stronę jQuery, znajdować najnowszą wersję, ściągać ją, a potem rozpakowywać do odpowiedniego katalogu. Te wszystkie czynności zrobił za nas Bower. Wystarczy tylko załadować bibliotekę w pliku HTML i już można z jej korzystać.

Bower konfiguruje się korzystając z dwóch opcjonalnych plików – .bowerrc oraz bower.json. Pierwszy z nich jest plikiem konfiguracyjnym, w którym najważniejszą opcją dla nas jest miejsce, w którym będą zapisywane biblioteki. Domyślnie biblioteki będą zapisywane w katalogu bower_components znajdującym się w tym samym katalogu, w którym wywołaliśmy Bowera. Drugi plik pełni podobą rolę co package.json – przechowuje informację o potrzebnych nam bibliotekach i ich wersji oraz opis projektu. bower.json generuje się poleceniem bower init lub można go stworzyć ręcznie.

W przypadku Bowera możliwe są konflikty związane z wersjami bibliotek. Biblioteka A może wymagać biblioteki B w pewnej wersji, a my mamy już zainstalowaną starszą. W takim wypadku Bower decyzję o tym, co ma robić zostawi nam.

Yeoman

yeoman

Ostatnim narzędziem dopełniającym nasz leniwy workflow jest Yeoman. Yeoman jest generatorem kodu, w którym dużą rolę odgrywają Grunt i Bower. Z jego pomocą można w łatwy i szybki sposób przygotować szkielet nowej aplikacji lub rozszerzyć istniejącą. Sam Yeoman po instalacji na niewiele się zdaje dopóki nie zainstalujemy któregoś z ponad 350 gotowych generatorów. Można tam znaleźć m.in. generatory AngularJS, Backbone, Ember, WordPress, aplikacji na FirefoxOS, aplikacji mobilnych, rozszerzeń Chrome’a i wiele innych. Po wygenerowaniu projektu wiele rzeczy zautomatyzuje za nas Yeoman wspólnie z Grunt i Bower.

Do pokazania pracy z Yeomanem postawimy projekt w Angularze. Na początku musimy zainstalować generator Angulara: npm install -g generator-angular. Następnie generujemy projekt: yo angular. Generator zada nam kilka pytań i utworzy szablonowy projekt, który jest dobrym punktem startowym. Poza samymi plikamy dostajemy również kilka tasków Grunta, z których możemy od razu korzystać. Wśród nich są taski do uruchamiania testów, kompilujące style czy przygotowujące aplikację do uruchomienia na docelowym serwerze. Do tego dostajemy do rąk zestaw generatorów ułatwiających rozwijanie aplikacji. Za pomocą jednego polecenia możemy dodać do projektu nowy kontroler, dyrektywę czy service, od razu mieć gotowy test jednostkowy i dodany tag wstawiający nowy kontroler/dyrektywę/service do pliku html.

Podsumowanie

W tych kilku prostych przykładach pokazałem jak szybko i niewielkim nakładem pracy zautomatyzować sobie pracę. Pozwoli nam to na zrzucenie części zadań na skrypty dając nam więcej czasu na właściwą pracę, czyli tworzenie działającego poprawnie kodu.

Podczas prezentacji poruszony został temat połączenia Grunta z Chrome DevTools. Pobieżnie przejrzałem temat i zdecydowałem, że poświęcę mu osobny artykuł. Ta integracja jest zbyt ciekawa, żeby potraktować ją po łebkach.

Niektórzy twierdzą, że wynalazł kolor czarny i że rządzi Mordorem. Miłośnik laserów, robotów, sów, kosmosów, wiewiórek i kotów.

  • Riu

    Dobry wpis. Mam taką refleksje, że ktoś kiedyś powinien policzyć ile trzeba zainstalować narzędzi zanim się zacznie pisać pierwsze „hello world”.

    • eRIZ

      Lepiej, że jest to jakoś ustandaryzowane niż wcale. Pamiętam doskonale czasy, w których w PHP nie było absolutnie żadnych narzędzi a’la menedżer pakietów i szok, gdy wskoczyłem w Node’a i pomimo dużej dowolności – o dziwo – większość developerów trzyma się standardów narzuconych właśnie przez opisywane narzędzia.

      IMO Composer został wprowadzony za późno. 😛

  • Maciej Płocki

    Co prawda minęła już chwila od publikacji tekstu ale dopiero teraz chciałbym podziękować za wpis – mój dev stał się prostszy i szybszy dzięki tym rozwiązaniom oraz w końcu się wziąłem za Angulara 😉

  • thejw23
  • Dzięki za wpis. To był dobry wstęp przed dalszym poznawaniem tych narzędzi 🙂

  • „Najlepiej przedstawić działanie Grunta na przykładzie prostej strony (która jest dostępna na GitHub)” – 404

  • Mateusz Chuchro

    Bardzo pobieżnie ale na wstęp w sam raz 🙂

Send this to friend

webmastah.weekly
Cotygodniowa porcja linków ze świata WEBDEV BEZ spamu, TYLKO samo mięcho!
Zobacz poprzednie wydania. Dołącz do 2 tysięcy webdeveloperów!
HTML5, CSS3, JS (React, Angular, Ember, Vue), PHP, SQL