Blog

Nuxt.js, czyli Vue na sterydach

Krótkie acz treściwe wprowadzenie do Nuxt.js, czyli frameworka do budowy aplikacji SPA czy SSR na bazie Vue.js.

Nuxt.js, czyli Vue na sterydach

Tytuł niniejszego wpisu, nawet jak na moje niezbyt wyśrubowane standardy, jest mało wyszukany ze wskazaniem na lichy. Na szczęście nie jest on mojego autorstwa i tym razem pozwoliłem sobie “tylko” zapożyczyć to określenie od człowieka, na którego materiały trafiłem poszukując mądrość w obszarze tytułowego Nuxta. Mimo całej wtórności tego określenia zdecydowałem się jednak na ten swoisty plagiat, ponieważ w mojej opinii nie najgorzej oddaje charakter rzeczonego narzędzia. Faktycznie rozwiązanie autorstwa francuskiego rodzeństwa – o znajomo brzmiącym nazwisku Chopin – szalenie upraszcza proces tworzenia aplikacji internetowych czy zwłaszcza prostych witryn budowanych przy wykorzystaniu dobrodziejstw, jakimi nas raczy Vue. Co więcej, można z powodzeniem używać Nuxta bez nawet podstawowej znajomości Vue, choć pewne rzeczy mogą być wówczas trudniejsze do realizacji, gdyż wymagać będą stosowana różnego rodzaju obejść i przez to psuć elegancję efektu końcowego.

Jednak po kolei, zacznijmy od krótkiego przedstawienia z czym mamy w tym wypadku do czynienia? Otóż jest to framework – co już została zasygnalizowane – przeznaczony dla aplikacji opartych na Vue, który ma umożliwić czy też ułatwiać ich renderowanie po stronie serwera. Oczywiście po pierwszej inicjalizacji tak aplikacja działa potem jako standardowe SPA (Single Page Application) napisane przy udziale Vue, ale takie rozwiązanie uwalnia nas od trosk związanych z problem SEO, gdyż istnieją uzasadnione obawy, że aplikacje SPA w czystej postaci mogą nie być przyjazne dla maszynek indeksujących wszelakich wyszukiwarek.

Jednakże Nuxt został przedstawiony światu prawie 3 lata po debiucie Vue, ale obecnie jest jednym z najpopularniejszych rozwiązań rozwijanych na bazie tego ostatniego. Pod koniec 2020 roku tygodniowa liczba pobrań przekroczyła pułap 300 tysięcy, co w przypadku “pochodnych” Vue jest wynikiem znakomitym, choć w porównaniu z jego odpowiednikiem dla Reacta to zaledwie trzecia część pobrań dla Nexta, bo o nim tutaj mowa. Z resztą należy wspomnieć, że twórcy Nuxta nie ukrywają, że inspiracją dla nich było właśnie Next.js, co ma swoje odzwierciedlenie w zapewne nieprzypadkowym podobieństwie nazw. Niestety z powodu zerowej znajomości Nexta trudno mi się wypowiedzieć, czy ewentualne podobieństwa wykraczają poza bezpośrednią inspirację oraz bliźniaczą prawie nomenklaturę. Wprawdzie moje pierwsze podejścia do nowoczesnych frameworków JS zaczęły się właśnie od Reacta jako tego najbardziej popularnego, ale dość szybko się okazało, że z tej mąki chleba nie będzie, bo wyjątkowo nie podeszła mi centralna dla tego ostatniego idea JSX. Tym samym Next.js jest mi równie bliski, co jQuery, czyli coś tam słyszałem, ale przyjemności tak naprawdę nigdy nie mieliśmy.

Zwyczajowo posypawszy głowę popiołem niewiedzy możemy przejści do tego, co stanowi istotę tego bloga, czyli słów parę na temat wrażeń piszącego te słowa. Od razu odkryję karty i napiszę, że obecnie trudno mi sobie wyobrazić robienie czegokolwiek w “czystym” Vue, choć muszę przyznać, że dość szybko się zadomowiłem w środowisku tego ostatniego, ponieważ nie ma krzty przesady w opiniach, że Vue jest szalenie przyjaznym rozwiązanie dla zupełnych nowicjuszy. Tym niemniej uważam, że Nuxt jest rozwiązanie, który poprzeczkę zawiesza jeszcze niżej, a przy tym znacząco usprawnia tworzenie aplikacji czy nawet prostych witryn internetowych za sprawą trzech kluczowych kwestii:

  1. prostego mechanizmu zarządzania routingiem, opierającego się na właściwym zarządzaniu strukturą plików,
  2. dodaniu koncepcji domyślnego szablonu dla tworzonej aplikacji, choć gwoli ścisłości powinno się używać tutaj liczby mnogiej, ponieważ takich „wzorców” może być tyle ile dusza zapragnie, czy też ile wymaga projekt,
  3. mechanizmu automatycznego importu komponentów Vue w obrębie tworzonego projektów.

Dwa pierwsze zagadnienia to rzecz jasna nic nowego w świecie tego typu rozwiązań, ale tutaj nie chodzi o odkrywanie wciąż na nowo Ameryki, ale zgrabne połączenie w jedną całość kilku elementów, by praca była efektywniejsza i przez to przyjemniejsza. Trzecia propozycja z tej perspektywy zdaje się najmniej wnosić, ale człowiek szybko przyzwyczaja się do dobrego.

Niestety dzisiejszy tekst ma charakter wyłącznie zajawkowy, zaś ja nadal jestem w trakcie poznawania tego rozwiązania, dlatego zapewne dopiero za dobre parę wpisów wprzód pokuszę się, by zaprezentować Nuxt.js w działaniu na bazie jakiegoś prostego projektu strony internetowej. W związku z tym dzisiaj będzie krótko o tym, jak to wszystko zostało połączone przez twórców tego frameworka w spójną całość. By to wyjaśnić kluczowe jest przyjrzeniu się strukturze katalogów każdej aplikacji tworzonej w ramach Nuxt. Domyślnie wygląda ona tak jak na załączonym niżej obrazku, zaś z perspektywy omawianych mechanizmów kluczowe są trzy katalogi, czyli /pages, /components oraz /layouts.

ZARZĄDZANIE ROUTINGIEM

Zacznijmy – a jakże – od punktu pierwszego, czyli mechanizmu rządzącego routingiem stron. Z tej perspektywy na warsztat należy wziąć katalog pages, co sugeruje już sama nazwa tego folderu. Idea nie jest nowa i sprowadza się ona do tego, że każdy plik z rozszerzeniem vue odpowiada pojedynczej stronie aplikacji. Na dzień dobry znajdziemy tam jeden tego typu plik, który nazywa index.vue i w tym przypadku odpowiada on ścieżce “/”. Jeśli w tym samym katalogu umieścimy inne pliki z rozszerzeniem vue, to zostaną one rozpoznane jako podstrony, których nazwa odpowiada nazwie pliku. Czyli na ten przykład plik kontakt.vue (jego zawartość) będzie odpowiadała za treść dostępną na podstronie nazwa.domeny/kontakt. Ten sam efekt można osiągnąć w inny sposób i choć nie wiem czy należy to traktować jako przejaw tak zwanych dobrych praktyk, ale osobiście polecam od początku przyzwyczajać się do tego podejścia, czyli w katalogu pages zostawić wyłącznie plik, który utworzony został już na starcie (oczywiście po wymaganych modyfikacjach). Inne podstrony wystarczy wówczas umieścić w podfolderach, których nazwy odpowiadać będą konkretnym podstronom, a następnie umieścić w nich plik o nazwie index.vue. Skoro efekt będzie dokładnie ten sam, to po co ta zabawa? To pewnie kwestia osobistych preferencji, ale po pierwsze takie rozwiązanie moim zdaniem poprawia czytelność projektowanej struktury aplikacji. Może w przypadku niewielkich projektów nie ma to większego znaczenia, ale przy większej liczbie plików taka segregacja może się okazać dość pomocna. Natomiast ważniejszy jest fakt, że wcześniej czy później staniemy przed koniecznością lub chociaż potrzebą tworzenia stron zagnieżdżonych. Dla przykładu możemy mieć stronę nazwa.domeny/team, na której zaprezentowane będą w kilku słowach sylwetki naszych współpracowników. Wykoncypujemy sobie przy tym, że po kliknięciu na zdjęcie “wybrańca” otworzy się podstrona, gdzie tej atencji dana osoba więcej uświadczy, a przy tym chcielibyśmy, żeby link do tej strony miał miał strukturę nazwa.domeny/team/nazwa-wybranego. Wówczas wystarczy utworzyć strukturę plików i folderów ja to pokazane zostało niżej. 

pages/

–| team/

—–| index.vue

—–| grzazynka.vue

—–| janusz.vue

—–| brajanek.vue

–| index.vue  

SZABLON PROJEKTU

Jeśli chodzi o szablon strony czy też aplikacji sama idea jest dość prosta i od dawien dawna stosowana w różnego sortu silnikach szablonów (template engine) i nie chodzi tutaj bynajmniej o reużywalność komponentów, czyli coś typowego dla samego Vue. Cały koncept opiera się bowiem na empirycznie potwierdzonym przekonaniu, że szkielet każdej strony lub przynajmniej pewne jej elementy są stałe czy też powtarzalne dla całej witryny czy tam domeny. Najlepszym tego przykładem może być nagłówek strony bądź też nawigacja górna oraz stopka (footer), którą w ramach spójności estetycznej zachowuje się zazwyczaj na każdej z podstron. W przypadku Nuxt na tę okoliczność wystarczy w bazowym czy też domyślnym szablonie wskazać właśnie te części wspólne, by następnie było one automatycznie dodawane do wyglądu już konkretnej strony obok tego, co dla niej samej unikalne czy tam charakterystyczne. Oczywiście w zależności od wielkości czy też złożoności konkretnej witryny takich “wzorców” może być więcej niż jeden, czyli poszczególne strony mogą “dziedziczyć” po różnych matrycach, ale nawet w przypadku tego samego szablonu dostępne są mechanizmy, które pozwalają stosować pewne odstępstwa od nadrzędnej formy, chociażby poprzez wykluczenie jakiegoś konkretnego elementu. 

W przypadku nowo utworzonej aplikacji Nuxt automatycznie generowany jest taki szablon zawierający jeden komponent w postaci znacznika HTML o nazwie Nuxt (patrz niżej) , choć de facto oznacza to, że tak naprawdę taką wspólną matrycą w tym momencie nie dysponujemy, ponieważ znacznik ten odsyła do tego, co unikalne dla każdej strony.

<template>

 <Nuxt />

</template>

Jeśli chcielibyśmy na ten przykład na każdej z stron widzieć na górze tę samą nawigację oraz u dołu jednakową stopkę, wówczas należy dodać nazwy stosownych komponentów do szablonu, a następnie zadbać, by w katalogu /components znalazły się odpowiadające im obiekty.

<template>

 <div>

   <TheNavbar />

   <Nuxt />

   <TheFooter />

 </div>

</template>

KOMPONENTY

Tym sposobem dochodzimy do trzeciej ze wspomnianych kwestii, czyli mechanizmy, który odpowiada za uproszczenie korzystania z komponentów w ramach tworzonego projektu. Same komponenty to rozwiązanie wprost z Vue, natomiast omówienie tego zagadnienie dalece wykracza poza zakres tego wpisu, który i tak niebezpiecznie się wydłuża. Dlatego napiszę jedynie, że ten podstawowy budulec Vue, który zawiera typowe składowe każdej aplikacji czy też witryny internetowej, a więc kod HTML, elementy stylu oraz w miarę potrzeby odpowiednie funkcjonalności napisane w JS. Z całą pewnością i temu zagadnieniu będę chciał poświęcić zapewne nie jeden wpis na tym blogu, ale na dzisiaj tyle musi wystarczyć, ponieważ kilka – i to dosłownie – ostatnich zdań  tego tekstu zarezerwowałem dla omówienia kwestii, jak w tym zakresie wspiera użytkownika.

Otóż w przypadku standardowego projektu Vue chcąc skorzystać z utworzonego komponentu musimy najpierw go wyeksportować w pliku źródłowym, by następnie w docelowym miejscu użyć go, importując go uprzednio. Całość wygląda dokładnie tak, jak ma to miejsce w przypadku obsługi modułów JS w zgodzie ze standardem ES6. W przypadku Nuxt wystarczy, że dodamy stosowny plik w folderze components i wówczas bez żadnych ekstra deklaracji, tak u źródła jak i docelowym miejscu. Rzecz jasna nic nie stoi na przeszkodzie, by robić to oldschoolowo i pewnie w dużych projektach nawet jest to wskazane, ale przy tworzeniu stosunkowo niewielkich projektach, a tylko takie mnie interesują, jest to naprawdę wygodna opcja.

KOŃCZĄC

Mimo że ten jest znacznie dłuższy niż zakładałem, siadając do jego napisania, to mam nieodparte wrażenie, że nie udało mi się odpowiednio zareklamować tego rozwiązania. Niestety nie są mi znane jakieś inne polskojęzyczne (a przy tym w miarę aktualne) źródła, gdzie wiedzę w tym zakresie można poszerzyć. Na szczęście dla władających lepiej lub gorzej narzeczem imć Szekspira w sieci o to nietrudno. Niestety – to mój największy zarzut do twórców tego rozwiązania – oficjalna dokumentacja mogłaby być bardziej obszerna. Na szczęście na oficjalnym blogu projektu można znaleźć kilka fajnych tutoriali, zaś dla preferujących materiały wideo na YT trochę tego znajdziecie. Osobiściem polecam kanał Debbie O’Brien, która piastuje formalnie funkcję lidera ambasadorów (to chyba dobre określenie) tego projektu.