- 2018 április 4
Előző cikkünkben bemutattuk a Webpack module bundler képességét, most pedig folytassuk a megismerését, mint asset loader, illetve néhány webpack plugint is megismerhetünk.

Hogyan működik loader-ként a webpack?

Először is, mit jelent az, hogy loader? Képesek vagyunk Webpack segítségével egy ES6 kompatibilis JavaScript fájlból ES5 kompatibilis változatot generálni, vagy SASS előfeldolgozóval írt stílusokból CSS fájlt létrehozni. Ezenkívül lehet képeket betölteni a html kódba külső forrásként, vagy akár base64 kódolással. Ezekhez a műveletekhez és még sok máshoz is loadereket használunk webpackben.

Ha még nem kezdtétek el használni az ES6 által nyújtott lehetőségeket, itt az ideje, ehhez a Babel JS-t fogjuk használni a következő példában. Telepítsük a szükséges NPM modulokat:

npm i babel-loader babel-core babel-preset-env --save-dev Sikeres telepítés után a webpack.config.js-ben meg kell adni a babel-loader-t a következőképpen: Mindig a module-n belül a rules tömbben soroljuk fel a különböző loader-eket. A use tulajdonságnak kell megadni a loader nevét, amit telepítettünk. A test értékével pedig azt határozzuk meg, milyen kiterjesztésű fájlokat figyeljen. Megadhatjuk az exclude-ban, hogy mely mappákat zárjuk ki a vizsgálatból, esetünkben a node_modules alatt szereplő könyvtárakat figyelmen kívül fogja hagyni.

Három babel csomagot telepítettünk fel, az egyik volt a babel-loader, a másik maga a Babel JS a babel-core csomagban és a harmadik volt, amiben definiálva van, melyik JavaScript verziót kezelje a Babel. Ehhez hozzunk létre a projektünk gyökér könyvtárában egy .babelrc fájlt, aminek a tartalma a következő legyen: Lassan összeáll a kép. Ha most lefordítjuk az előző cikkünkben megírt kódot, az eredményben nem fogunk változást találni, de még nem is változtattunk a saját kódunkon. Ezt most tegyük meg a következőképpen: Mennyivel szebb így! Ha nem lenne ismerős az arrow függvény szintaxis, akkor még ma nézz utána, érdemes, illetve használhatjuk az ES6 által nyújtott import/export lehetőségeket. Ha ezek után lefuttatjuk az npm run build paranccsal a kódot, akkor azt figyelhetjük meg a bundle.js -ben, hogy az ES6-os kódunkat ES5 formára hozta. Így a fejlesztői környezetben tudjuk használni az új feature-ket, éles környezetben pedig a Webpack megoldja nekünk a kompatibilitást, vagyis a Webpack a Babel JS segítségével.

Hogyan töltsünk be formázott képeket?

Ahogy a JavaScriptekhez, ugyanúgy a stíluslapokhoz is léteznek loaderek. Lehet JavaScriptbe importálni egy css fájlt, amit a CSS loader felismer és a Style loader beilleszti style tagek közé, de akár Preprocesszort is használhatunk, hiszen létezik Sass loader, Less loader, Stylus loader is. A következő példában a JavaScript fájlunkba töltsünk be egy képet és egy css fájlt, amivel a képet formázzuk. Az image.js tartalma: Az image.js az index.js-el van egy szinten az src mappában. A képet JavaScript-el illesztjük az oldalunkba és a lorempixel.com-ot használjuk forrásként. Csináljunk az src mappába egy styles mappát és hozzuk létre benne az image.css-t: Igazából a formázás teljesen mindegy, én a példa kedvéért ezt a két tulajdonságot adtam meg. Most telepítsük fel a szükséges loadereket a következő paranccsal: npm i css-loader style-loader --save-dev Ha feltelepültek a loadereket, a webpack.config.js-t egészítsük ki a következő szabályokkal: Amint látható a style-loader és a css-loader lett felvéve a .css kiterjesztésű fájlok esetén. Először a css-loader fogja a fájlokat megvizsgálni, majd a style-loader fog lefutni. Ezt azért fontos kiemelni, mert a kiértékelési sorrend a use-nál megadott tömbben fordított sorrendben történik.

Készítsünk a gyökér könyvtárba a package.json mellé egy index.html fájlt a következő tartalommal: Majd ezt fogjuk megnyitni a teszteléshez, és még egy változtatást kell végeznünk, méghozzá az index.js-be beimportálni az image.js-t: Jöhet a buildelés az npm run build paranccsal. A konzolban a kimenet most már beszédesebb:

webpack Látható, hogy az image.js és az image.css is feldolgozásra kerül és a honlapon megjelenik a JavaScript által betöltött formázott kép:

webpack

Használhatunk Plugineket is

Az előző fejezetben megnéztük, hogyan tudja a Webpack megoldani, hogy style tag-ek közé kerüljön a css fájlunk tartalma. Most nézzük, meg azt, hogyan lehet link tag-el a Webpack által generált bundle css-t beilleszteni a html fájlunkba. Ehhez szükségünk lesz egy pluginre, aminek a neve Extract Text Webpack Plugin, telepítsük fel a következő paranccsal:

npm i extract-text-webpack-plugin --save-dev A webpack.config.js-ben fogjuk a plugint felhasználni, ahova require-rel húzzuk be legelőször, majd a modul szabályoknál a css szabályt is módosítani kell, végül pedig meg kell adni a pluginek között a plugin példányosítását. A kód a következőképpen fog kinézni: A példányosításnál megadtunk egy style.css stringet, ami azt fogja jelenteni, hogy ilyen néven készíti el a Webpack a generált css fájlt. Ahhoz, hogy buildelés után megfelelően működjön, még az index.html -be fel kell venni a style.css hivatkozást. Próbáljuk ki, készítsünk egy buildet és nézzük meg, hogy sikerült. Nálam a következő kimenet látható:

webpack

Egy probléma van ezzel, méghozzá az, hogy a scripteket és css fájlokat nekünk kell beilleszteni a html fájlba. Van erre is egy plugin, aminek a neve HTML Webpack Plugin, telepítsük a következő paranccsal: npm i html-webpack-plugin --save-dev Azt szeretnénk elérni, hogy a Webpack menedzselje az index.html fájlunkat, ezért másoljuk át az src mappába és szedjük ki belőle a script és a link tageket.

A webpack.config.js-ben is szükséges hozzáadni a plugint, először require-el behúzzuk a csomagot, majd a plugin részt egészítjük ki a következőképpen: A HtmlWebpackPlugin példányosítás során a template paraméternek megadjuk a html fájl elérhetőségét. Nyomjunk egy buildet és a kimeneten látható, hogy a Webpack készíti el a css, a js és a html fájlt is a számunkra.

webpack

A Webpack által kezelt webalkalmazásoknál, az asset fájlok cache-lését maga a Webpack oldja meg. A művelet végtelenül egyszerű: a webpack.config.js -ben a filename tulajdonságot nevezzük át ‘bundle.js’ -ről ‘bundle.[hash].js’ -re és tegyük meg ugyanezt a ‘style.css’ -nél is, ott legyen ‘style.[hash].js’ a helyettesítő, amivel kiegészítettük arra szolgál, hogy egy hash kódot illeszt a fájlnévbe, ami egyedivé teszi és mivel a fájlnév egyedi, a Webpack gondoskodik arról is, hogy az index.html fájlunkba a megfelelő asset fájlnév kerüljön: Használhatjuk még a [chunkhash] helyettesítőt is, ami chunk specifikus hash-t generál a fájlnévbe, vagyis ha buildelünk nem változik, míg a [hash] helyettesítő build specifikus, minden buildelés során új hash generálódik és új fájl jön létre. Ha többször is lefuttatjuk a buildet úgy hogy változtatunk valamelyik JavaScript fájlon vagy a CSS fájlon látható, hogy a dist mappába folyamatosan új fájlok jönnek létre. Ez azért így elég kellemetlen tud lenni, de ehhez is létezik egy Webpack Plugin, amit a következő paranccsal installáljunk:

npm i clean-webpack-plugin --save-dev Elég egyértelmű a használata, require-el behúzzuk, majd a plugineknél példányosítjuk és persze megadjuk melyik mappákat takarítsa ki. Itt tömbben adjuk meg a mappákat, meg lehet egyszerre többet is.

Kedvenc funkcióm: code splitting

Itt először is hadd magyarázzam el, miről is van szó. Képzeljük el, hogy van egy beléptető oldalunk, ha a felhasználó belépett egy dashboard (irányítópult) oldallal találkozik, ahol sok grafikon, táblázat, különböző statisztikák várják. Az biztos, hogy egy beléptetéshez jóval kevesebb JavaScript-re van szükségünk, mint egy komolyabb dashboard oldalon és most képzeljük el, hogy mi lenne, ha a belépés gombra kattintva töltődnének be azok a JavaScript-ek, amikre a dashboard oldalon van szükség. Nézzük meg egy egyszerű példán keresztül. Változtassuk meg az index.js fájlunkat a következőképpen:

Amint látható létrehoztunk egy gombot, aminek a Click szöveget adtuk meg és hozzáadtunk egy esemény kezelőt. Ha rákattintunk a gombra, akkor töltsük be a System.import segítségével az image modult. A fájl végén hozzáadjuk a body-hoz a gombot. Az image.js -ben pedig csak annyit változtattunk, hogy az elem létrehozását export default függvénybe helyeztük. Gyakorlatilag készen is vagyunk a kódunk módosításával és elmondhatjuk, hogy megírtuk az első code splitting kódunkat dinamikus import segítségével. Fordítsuk le a kódot újra az npm run build segítségével és nyissuk meg az index.html fájlt böngészőben, majd a Chrome DevTools-t nyissuk elő az F12 segítségével, itt kattintsunk a Network fülre és ott is a JS re szűrjünk rá. Töltsük be újra az oldalt és kattintsunk a click gombra, a következő eredményet kell látnunk:



Látható, hogy a kattintás után betöltődik a 0.bundle js, erről szól a code splitting, a szükséges scripteket csak bizonyos események bekövetkeztekor töltjük be. Ha nagyobb méretű a JS fájl akkor illik egy loading képernyőt elhelyezni a két oldal közé.

Állítsuk be a fejlesztői környezetet

Azt mindenki jól tudja, hogy a fejlesztői környezet és az éles környezet más-más funkcionalitást igényel. Ha fejlesztünk és DEV módban vagyunk, akkor szeretjük ha olvasható a forrás és nincs tömörítve, illetve a legnagyobb segítség ha Livereload/BrowserSync segítségével a kód módosításakor újratöltődik a böngésző vagy legalább is a stíluslapok. Éles környezetben viszont ezekre nincs szükség, amire viszont van, az a minify. Így tehát két különböző config-ra van szükség, hiszen le kell kezelnünk a DEV módot és a PROD módot. Kezdjünk is hozzá.

Telepítsük a fejlesztői szervert a következő paranccsal: npm i webpack-dev-server --save-dev

Ha sikeresen feltelepült a webpack-dev-server csomag, akkor vegyük fel a webpack.config.js fájlban a devServer-hez tartozó részt a következő kód alapján: A contentBase tömbben azt adjuk meg, melyik könyvtárakat kezelje le. A port azt mondja meg, melyik porton nyissa meg az alkalmazást. Az open paraméterrel pedig bekapcsolhatjuk, azt hogy egyből megnyissa a böngészőben.

A következő lépésben a package.json fájlunkat fogjuk módosítani: Megváltoztattuk a build scriptet annyival, hogy egy -p opciót adtunk meg. Ez azt jelenti, hogy a webpack így tömöríti a JS és CSS fájlokat (minify).

Csináltunk egy dev scriptet is, ahol a webpack-dev-server parancsot hívjuk meg a –hot és az –inline paraméterekkel. Ezek szükségesek a Webpack egyik új fejlesztéséhez a Hot Module Replacement (HMR)-hez.

Töröljük ki a build mappa tartalmát és futtassuk az npm run dev parancsot. Ha mindent jól állítottunk be, akkor a következő kimenetet kapjuk és egy pár másodperc után az éppen aktív böngésző ablakban megnyílik az alkalmazásunk a localhost:8800-as címen:

webpack

Próbáljunk meg módosítani az image.css vagy bármelyik JavaScript fájlban majd mentsünk rá és láthatjuk hogy a böngésző befrissül. Ha jobban szemügyre vesszük mi is történt egy érdekes dologra lehetünk figyelmesek, a kitöröld build mappa nem jön létre. Ez azért történik, mert rájöttek, hogy fejlesztői környezetben túl erőforrás igényes a folyamatos fájl írás és olvasás, ezért a HMR -nél a bundle-k a memóriában tárolódnak, így sokkal gyorsabb választ kapunk.

Az alkalmazásunkat úgy állítsuk be, hogy a fejlesztői környezetben az npm run dev parancsot használjuk, míg az éles környezetnél, lehetőleg a deploy során az npm run build parancsot futtassuk.

Összegzés

Ahogy láthattuk a Webpack nem pusztán module bundler, sokkal több mindenre képes. Összehozza a frontend fejlesztő számára mind a környezetet, mind pedig a szükséges technológiákat, ahhoz hogy a lehető leghatékonyabban tudjon programozni.

Ha ismerős a BrowserSync vagy a Livereload, akkor a Webpack-nek van rá megoldása, méghozzá a Hot Module Reload. Ha használtál már Gulp-ot a CSS és JS fájlok összegyúrására, fordítására, akkor most kipróbálhatod a Webpack Loaderek hogyan oldják meg ugyanezt a problémát. Ezen kívül tudjuk menedzselni a képek betöltését, a Webpack képes a cachelésre is hatékony megoldást adni, van code splitting-ünk, amivel csak a szükséges esetben töltődik be a kódunk és így tovább.

Nekem nagyon megtetszett a használata és az egyre erősödő közösség is azt bizonyítja, hogy megéri áttérni a Webpack használatára, főleg amióta kijött a Webpack 4, ahol akár 98%-kal gyorsabb is lehet a futtatás.

3 hozzászólás

  • Tóth Gábor szerint:

    Szia,
    ki tudod tenni a projektet github / gitlabra? Mert összeraktam a leírtak szerint a code splitting-ig, de nekem folyton elszáll mikor elindítom a build-et.

    Köszönöm előre is.

  • Tóth Gábor szerint:

    Szia,

    köszönöm.

    A extract-text-webpack-plugin elavult lett 4.0-tól helyette a mini-css-extract-plugin -t kell használni.

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöljük.