Nézetek 3. rész - Eszközkészlet összeállítás a Laravel Mix és Webpack segítségével

Attila | 2022. 03. 12. 10:42 | Olvasási idő: 4 perc

Címkék: #CSS #JavaScript #Laravel #Laravel Mix #Nézet (View) #npm #SCSS #Webpack

Talán még emlékszünk a Github-os projekt clone-ozására (ha nem, akkor a bejegyzés elején linkelem a tartalmat). Abban azt állapítottam meg, hogy vannak olyan fájlok és mappák, amelyeket a Github nem tárol el, mert clone-ozás után mindenki le tudja őket generálni a saját lokális környezetében. Ilyen volt például a vendor mappa, amelyet a composer-rel a composer.json fájl felhasználásával generáltunk, vagy például a node_modules mappa, aminél pedig az npm csomagkezelővel a package.json fájlt használtuk fel a generálásra. De a public mappa is különleges ilyen szempontból, mivel annak a részeit (CSS, JavaScript, kép), mappákat és fájlokat is helyben tudunk generálni, csak egy kicsit eltérő módon, mint az imént említetteket. Ebben a bejegyzésben megnézzük, hogy hogyan tudjuk legenerálni a public mappa részeit és miként működik ez a gyakorlatban.
laravel-webpack

A bevezetőben említett clone-ozásos bejegyzés itt található: Laravel projektek clone-ozása a Github-ról

A blogbejegyzés vezető képe a Webpack oldaláról származik. Azért választottam ezt, mivel nagyon jól megmutatja, hogy mi is történik a háttérben, most pedig ezt fogjuk boncolgatni. Ha nagyon röviden már a legelején össze szeretném foglalni, akkor azt tudnám elmondani, hogy ennek segítségével fogjuk a kliens oldali (például CSS, JavaScript) fájljainkat lefordítani és optimalizálni, hogy amikor majd a felhasználó gépére ténylegesen eljutnak ezek a kódok, akkor a lehető legkevesebb sávszélességet használják és így minél gyorsabban megjelenjenek.

Kevésbé gyakorlott Frontend fejlesztők - mint akár én is - kérdezhetnénk, hogy de hát a CSS és JavaScript kódokat a felhasználó böngészője tudja értelmezni és felhasználni... minek kellene nekünk ehhez lefordítani és optimalizálni? A kérdésre a válaszhoz gondoljuk át egy pillanatra, hogy manapság már a lehető legritkábban fordul az elő, hogy valaki "natív" ír simán csak CSS és JavaScript kódokat. Mindenki használ (még ha nem is feltétlenül tud róla) valamilyen kliens oldali keretrendszert azért, hogy kényelmesebbé tegye a saját munkáját. Ha pedig feltételezzük, hogy a kliens oldali programozók használnak ilyeneket, akkor azt is el kell fogadnunk, hogy érdemes lenne "összeintegrálni" a felhasznált keretrendszerek releváns kódjait, és azt együttesen átadni a felhasználó böngészőjének. Ekkor már szükség van arra, hogy a kliens oldali csomag (keretrendszer) függőségeket feloldjuk, és a lefordított, optimalizált kódokat küldjük vissza a kérés eredményeként a felhasználó böngészőjének. Optimalizálás kapcsán nézzük csak meg például mondjuk az egyik legismertebb, Bootstrap keretrendszer aktuális verziójának minimalizált CSS fájlját:

A kód mindössze néhány sort tartalmaz és a lényegi rész valójában csak egy darab sorból (de persze jó sok karakterből) áll. Ezzel dolgozni és átlátni elég nehézkes lenne, viszont olyan szempontból jó, ha csak fel akarjuk használni ezt, és ilyen optimalizált formában küldeni vissza a felhasználó böngészőjének.

A Webpack tehát ebben lesz hasznunkra, mi viszont ezt egy "Laravel-re alkalmazott, csomagolt formában" fogjuk használni, mivel Jeffrey Way, a Laracasts oldal vezetője készített hozzá egy úgynevezett wrapper-t, amit Laravel Mix-nek nevezett el (dokumentáció, forráskód, videósorozat, kiterjesztések elérhetők a weboldalán). A Laravel Mix-et minden Laravel projekt alapértelmezetten tartalmaz fejlesztői (dev(eloper)) függőségként, ha megnézzük a package.json fájlunkat, akkor ott láthatjuk is (nálam most a 6.0.6-os verziót használja a 9-es Laravel).

Van továbbá egy nagyon fontos fájlunk, amely belépési pontként szolgál ahhoz, hogy lefordítsuk és optimalizáljuk a kliens oldali kódjainkat, ez a webpack.mix.js fájl. Ebben láthatunk akár (attól függően, hogy milyen verzióját használjuk a Laravel-nek) js, sass vagy postCss nevű metódusokat .-tal (ponttal) hozzáfűzve a mix JavaScript objektumhoz. A felsorolt metódusok közös jellemzője, hogy az első paraméter szolgál arra, hogy a Laravel projektünk resources mappájában lévő fájlokat fogja lefordítani és optimalizálni, majd a metódus második paramétere szerint "átmásolja" az eredményt a public mappa megfelelő helyére. Így tehát a metódusok első paramétere a forrásfájl (resources mappa), a második paramétere a célkönyvtár (public mappán belül). Persze a célkönyvtár esetén lehetünk specifikusabbak is és akár már ott megnevezhetjük a célfájl nevét, ha mondjuk nem ugyanúgy akarjuk hívni forrás- és céloldalon az adott fájlt. (Megjegyzés: a későbbiekben persze fogjuk még másra is használni ezt a webpack.mix.js fájlt, de most egyelőre elég ennyit tudnunk róla.)

Beszéltem már fordítási folyamatról a kliens fájljainknál, most nézzük meg, hogy mi alapján fog ez történni. Nyissuk meg a package.json fájlt a projektünk gyökerében és nézzük meg a "scripts" részt. Ezek a bal oldalon látható kulcsok gyakorlatilag alias nevek parancshívásokra, amelyek során az npm-et és a mix-et fogjuk használni.


Ennyi elméleti bevezető után, térjünk rá a gyakorlati részre. Ha megnézem a jelenlegi projektemet, akkor azt látom, hogy a resources mappában van css mappa, de abban az app.css üres, 0 lényegi sort tartalmaz. Viszont! a public mappában lévő css/app.css fájlba, mi az előző blogbejegyzésben bemásoltuk a template-ünk CSS kódját. Ha tehát most elindítanánk a fordítási folyamatot, akkor a public mappában lévő css/app.css fájl tartalma felülíródna a resources/css/app.css üres fájl alapján, ami nyilván nem lenne jó nekünk. Szóval a fordítási folyamat előtt cseréljük meg a két fájl tartalmát (public/css/app.css --> resources/css/app.css). A js nevű mappa nincs a public-ban, úgyhogy azzal nem kell foglalkoznunk egyelőre, az majd létre fog jönni a fordítás után. Na de akkor fordítsunk! A fordítást a Webpack-ot becsomagoló Laravel Mix fogja elvégezni. Adjuk ki a parancsot:

npm run dev

Láthatjuk utána, hogy a fenti "script"-ek szerint történik meg az "alias-ok mentén" (npm run dev --> npm run development --> mix) az utasítások hívása:

Viszont aztán hibát kaptunk, mert azt jelzi, hogy a mix parancsot nem ismeri fel. Oldjuk ezt meg:

npm install

Ennek hatására ugye létrejön a projekt mappánk gyökerében a node_modules mappa és benne a kliens oldali függőségek csomagjai lesznek. Utána már hívhatjuk újra az npm run dev parancsot, az eredménye pedig itt látható:

Szerencsére "zöld" választ kaptunk és azt írja, hogy sikeresen megtörtént a fordítás. Ellenőrizhetjük is az eredményt, ami ugye a public mappában fog látszódni. Elsőként látható, hogy js mappa létrejött, benne az app.js fájllal. A tartalma pedig jó terjedelmes, főleg ha csak azt nézzük, hogy a resources/js/app.js forrásfájl mindössze egyetlen sort tartalmazott. Itt tehát egyértelműen látszódik, hogy a függőség "belefordítása" a kliens oldalra szánt public/js/ célkönyvtárban lévő app.js fájlba.

Az app.css kapcsán elmondható, hogy ugyanúgy néz ki a nyers, mint a lefordított és optimalizált fájlunk (talán csak a plusz sortörések hiányoznak belőle), de ez így rendben is van, hiszen egy sima CSS fájlnál nincs szükség fordításra. Mi van akkor viszont, ha mi egy CSS előfeldolgozót (preprocessor) használunk, tehát valamilyen SASS, LESS, STYLUS kódot...? Aki ezekkel nem lenne tisztában, de a sima CSS-t ismerik, azoknak mindenképpen ajánlok egy videót, amiben egész jól elmagyarázzák a SASS működését (ha pedig ezt megértjük, akkor a LESS és STYLUS működése is kísértetiesen hasonló, szóval azokkal sem lehet gondunk): Ismerd meg a SASS-t | CSS extrákkal Itt kb. 45 perc alatt egész sokmindent megtudhatunk a SASS működéséről. Megjegyzés: ha valaki nem akarja beleásni magát a SASS rejtelmeibe, annak annyit tudnék nagyon röviden elmondani, hogy ennek segítségével tudjuk kicsit programozottan kezelni a stílusszabályainkat, változókkal, függvényekkel, beágyazással, öröklődéssel... szóval tényleg programozhatjuk a segítségével a CSS-ünket. Mi most egy nagyon minimális kódot írunk SASS-ben, csak azért, hogy lássuk, mi történik a fordítás során:

  • Hozzunk létre egy új fájlt ide: resources / sass / mystyle.scss
  • Adjuk hozzá a következő tartalmat a mystyle.scss fájlunkhoz (egy $primary változónak az értékét beállítjuk pirosra, majd ezt a változót állítjuk be a p - bekezdés - betűszínének):

  • A fordításhoz pedig bővítenünk kell a webpack.mix.js fájl tartalmát (vegyük észre, hogy ez egyetlen utasítás, a mix objektumhoz csak .-tal vannak hozzáfűzve az újabb sorok, de még ugyanannak az utasításnak a részeként):

Majd pedig mentsük el az új fájlokat és indítsuk el a fordítási folyamatot az npm run dev utasítással (előfordulhat, hogy egymás után kétszer is ki kell adnunk parancsot, mert időközben kijöhetett valamelyik kliens oldali csomag újabb verziója és előtte azt telepítenie kell). Sikeres fordítás után már a mystyle.css is bekerült a lefordított fájlok táblázatába:

De nem csak ide került be, hanem a mystyle.css (már nem scss kiterjesztéssel!) bekerült a public / css mappába. Nézzük meg az oda bekerült új fájl tartalmát:

Ez már csak a lefordított kódot tartalmazza, ahol a korábban deklarált és inicializált $primary változó értéke bekerült a p stílusdefiníciójába. Ez így nagyon jó, viszont még nem vagyunk készen, ugyanis ez a változtatás még nem fog érvényre kerülni a weboldalunkon, hiszen ezt a mystyle.css fájlt még nem importáltuk be a layout.blade.php nézet fájlunk head részében. Ezt fogjuk most megtenni a következő sor beszúrásával:

A mix segédfüggvény segít nekünk abban, (amiben korábban az asset is segített), hogy megtalálja a rendszer a css fájl helyét a public mappán belül, de ezzel a mix metódussal jelezzük azt is a rendszernek (és magunknak is), hogy ez egy lefordított stílusokat tartalmazó fájl. Ha ezután (kiszolgáljuk és) betöltjük a weboldalunkat a böngészőben, akkor már piros betűszínnel fognak megjelenni a bekezdéseink, nagyjából így:

Megjegyzés: lokálisan működnének amúgy a CSS importálásaink úgy, hogy se asset(), se mix() metódusokat nem használunk a betöltésükhöz. A probléma akkor keletkezne, ha feltelepítenénk egy távoli kiszolgálóra a weboldalunkat, és akkor azt tapasztalnánk, hogy a CSS és JS fájljainkat nehézkesen tudnánk beimportálni... ha viszont használjuk az asset() és mix() segédmetódusokat, akkor ilyen problémánk nem lehet, úgyhogy használjuk ezeket már lokálisan is, hogy a későbbi problémákat elkerüljük.

Tipp: ha éppen a webalkalmazásunk frontend-jével foglalkozunk, vagyis annak stílusával, akkor a kényelem miatt érdemes nem az npm run dev parancsot futtatni, hanem lehetőségünk van használni az npm run watch parancsot is. Ekkor ha bármit megváltoztatunk a webpackos (Mix-es) forrásfájljainkban és elmentjük őket a változtatás után, akkor automatikusan lefut a fordítási folyamat, nem kell nekünk újra és újra kiadni a korábbi npm run dev parancsot.

A bejegyzés kódjai ebben a commit-ben találhatók: ITT.