Articles

Egy ES6 projekt beállítása a Babel és a webpack használatával

Ebben a cikkben a modern (webböngészőkben futó) JavaScript kezelésére szolgáló építési beállítások létrehozását fogjuk megvizsgálni a Babel és a webpack segítségével.

Ez azért szükséges, hogy a modern JavaScript kódunkat a böngészők szélesebb körével kompatibilissé tegyük, mint amilyenek egyébként lennének.

A JavaScript, mint a legtöbb webes technológia, folyamatosan fejlődik. A régi szép időkben néhány <script> taget beilleszthettünk egy oldalba, esetleg jQuery-t és néhány plugint, és már készen is voltunk.

Az ES6 bevezetése óta azonban a dolgok fokozatosan bonyolultabbá váltak. Az újabb nyelvi funkciók böngészőtámogatása gyakran hiányos, és ahogy a JavaScript-alkalmazások egyre ambiciózusabbá válnak, a fejlesztők modulokat kezdenek használni a kódjuk rendszerezésére. Ez viszont azt jelenti, hogy ha ma modern JavaScriptet írsz, be kell vezetned egy build-lépést a folyamatodba.

Amint az alábbi linkekből láthatod, az ES6-ról ES5-re való visszaváltás drámaian megnöveli a támogatható böngészők számát.

  • ES6 kompatibilitás
  • ES5 kompatibilitás

A build rendszer célja, hogy automatizálja azt a munkafolyamatot, amely ahhoz szükséges, hogy a kódunk készen álljon a böngészőkre és a gyártásra. Ez olyan lépéseket foglalhat magában, mint a kód átfordítása egy eltérő szabványra, a Sass CSS-re történő fordítása, a fájlok csomagolása, a kód kicsinyítése és tömörítése, és még sok más. Ahhoz, hogy ezek következetesen megismételhetők legyenek, szükség van egy build rendszerre, amely egyetlen parancsból ismert sorrendben indítja el a lépéseket.

Előfeltételek

Hogy követni tudjuk, telepíteni kell a Node.js-t és az npm-et (a csomagban együtt érkeznek). Javaslom, hogy egy verziókezelőt, például az nvm-t használd a Node telepítésének kezelésére (itt találod, hogyan), és ha szeretnél egy kis segítséget az npm kezeléséhez, akkor nézd meg a SitePoint kezdőbarát npm bemutatóját.

Beállítás

Hozz létre egy gyökérmappát valahol a számítógépeden, és navigálj bele a terminálból/parancssorból. Ez lesz a <ROOT> mappád.

Hozz létre egy package.json fájlt ezzel:

npm init -y

Figyelem: A -y flag alapértelmezett beállításokkal hozza létre a fájlt, és azt jelenti, hogy a parancssorból nem kell kitöltened a szokásos részleteket. Ezeket később a kódszerkesztőben módosíthatja, ha szeretné.

A <ROOT> mappában hozza létre a src, src/js és public könyvtárakat. A src/js mappába fogjuk tenni a feldolgozatlan forráskódunkat, a public mappába pedig az átfordított kód fog kerülni.

Transpiling with Babel

Az induláshoz telepíteni fogjuk a babel-cli-t, amely lehetővé teszi az ES6 ES5-re történő átfordítását, valamint a babel-preset-env-t, amely lehetővé teszi, hogy az átfordított kóddal meghatározott böngészőverziókat célozzunk meg.

npm install babel-cli babel-preset-env --save-dev

Az package.json-ben most már a következőket kell látnunk:

"devDependencies": { "babel-cli": "^6.26.0", "babel-preset-env": "^1.6.1"}

Míg a package.json fájlban vagyunk, változtassuk meg a scripts részt, hogy így szóljon:

"scripts": { "build": "babel src -d public"},

Ez lehetővé teszi számunkra, hogy a Babel-t egy szkript segítségével hívjuk meg, nem pedig minden alkalommal közvetlenül a terminálból. Ha többet szeretnél megtudni az npm szkriptekről és arról, hogy mire képesek, nézd meg ezt a SitePoint bemutatót.

Végül, mielőtt tesztelhetnénk, hogy a Babel teszi-e a dolgát, létre kell hoznunk egy .babelrc konfigurációs fájlt. Ez az, amire a babel-preset-env csomagunk hivatkozni fog a transzpile paramétereihez.

Készítsünk egy új fájlt a <ROOT> könyvtárban .babelrc néven, és illesszük bele a következőket:

{ "presets": } } ] ]}

Ezzel beállítjuk, hogy a Babel minden böngésző utolsó két verzióját, valamint a Safari v7 vagy magasabb verzióját transzpilezze. Más beállítások is rendelkezésre állnak attól függően, hogy mely böngészőket kell támogatni.

Azzal, hogy ezt elmentettük, most kipróbálhatjuk a dolgokat egy ES6-ot használó JavaScript mintafájllal. Ennek a cikknek a céljaira módosítottam a leftpad egy példányát, hogy számos helyen ES6 szintaxist használjon: sablon literálok, nyílfüggvények, const és let.

Mentsd el ezt src/js/leftpad.js néven, és a terminálodból futtasd a következőt:

npm run build

Ha minden a terv szerint halad, a public mappában most már egy új fájlt kell találnod js/leftpad.js néven. Ha ezt megnyitod, látni fogod, hogy már nem tartalmaz semmilyen ES6 szintaxist, és így néz ki:

Kódod szervezése ES6 modulokkal

Az ES6 modul egy olyan JavaScript fájl, amely függvényeket, objektumokat vagy primitív értékeket tartalmaz, amelyeket egy másik JavaScript fájl számára kívánsz elérhetővé tenni. Az egyikből export, a másikba pedig import kerül. Minden komoly, modern JavaScript projektnek fontolóra kell vennie a modulok használatát. Lehetővé teszik, hogy a kódot önálló egységekre bontsa, és ezáltal könnyebben karbantarthatóvá tegye; segítenek elkerülni a névtérszennyezést; és segítenek a kódot hordozhatóbbá és újrafelhasználhatóbbá tenni.

Míg az ES6 szintaxis nagy része széles körben elérhető a modern böngészőkben, a modulok esetében ez még nem így van. A cikk írásakor a Chrome-ban, a Safariban (beleértve a legújabb iOS-verziót is) és az Edge-ben érhetőek el; a Firefoxban és az Operában egy zászló mögé vannak rejtve; az IE11-ben és a legtöbb mobileszközön pedig nem elérhetőek (és valószínűleg soha nem is lesznek).

A következő részben megnézzük, hogyan integrálhatjuk a modulokat a build beállításainkba.

Export

Az export kulcsszó az, ami lehetővé teszi, hogy az ES6 moduljainkat elérhetővé tegyük más fájlokban, és erre két lehetőséget ad: a névre szólót és az alapértelmezettet. A named export segítségével modulonként több exportálási lehetőségünk is lehet, az alapértelmezett exportálással pedig modulonként csak egy. A megnevezett export különösen akkor hasznos, ha több értéket kell exportálnunk. Például lehet, hogy van egy modulunk, amely számos segédfüggvényt tartalmaz, amelyeket az alkalmazásokon belül több helyen is elérhetővé kell tenni.

A leftPad fájlunkból tehát csináljunk modult, amelyet aztán egy második fájlban igényelhetünk.

Névre szóló export

A névre szóló export létrehozásához a leftPad fájl aljára a következőket írjuk:

export { leftPad };

A "use strict"; deklarációt is eltávolíthatjuk a fájl tetejéről, mivel a modulok alapértelmezés szerint strict módban futnak.

Hibás exportálás

Mivel a leftPad fájlban csak egyetlen exportálandó függvény van, valójában jó jelölt lehet a export default használatára helyette:

export default function leftPad(str, len, ch) { ...}

Az "use strict"; deklarációt ismét eltávolíthatjuk a fájl tetejéről.

Import

Az exportált modulok felhasználásához most importálnunk kell őket abba a fájlba (modulba), amelyben használni szeretnénk őket.

A export default lehetőségnél az exportált modul tetszőleges néven importálható. Például a leftPad modult importálhatjuk így:

import leftPad from './leftpad';

Vagy más néven is importálhatjuk, például így:

import pineapple_fritter from './leftpad';

Funkcionálisan mindkettő pontosan ugyanúgy működik, de nyilvánvalóan érdemes vagy ugyanazt a nevet használni, mint ami alatt exportáltuk, vagy valami olyat, ami érthetővé teszi az importálást – esetleg ahol az exportált név ütközne egy másik változó nevével, ami már létezik a fogadó modulban.

A névvel történő exportálás esetén ugyanazt a nevet kell használnunk a modul importálásakor, mint ami alatt exportáltuk. A mi példamodulunk esetében hasonló módon importálnánk, mint a export default szintaxis esetében, de ebben az esetben az importált nevet szögletes zárójelekkel kell körülvennünk:

import { leftPad } from './leftpad';

A zárójelek kötelezőek a named export esetén, és ha nem használjuk őket, a program sikertelenül fog működni.

A named export nevét importáláskor szükség esetén meg lehet változtatni, ehhez a import as szintaxis segítségével egy kicsit módosítanunk kell a szintaxisunkat. A export-hez hasonlóan ennek is többféle módja van, amelyek mindegyike részletesen megtalálható az MDN import oldalán.

import { leftPad as pineapple_fritter } from './leftpad_es6';

A névváltoztatás megint csak egy kicsit értelmetlen, de jól szemlélteti, hogy bármire megváltoztathatók. Mindig tartsuk be a jó névadási gyakorlatot, kivéve persze, ha gyümölcsalapú receptek elkészítéséhez írunk rutinokat.

Az exportált modul fogyasztása

Az exportált leftPad modul használatához a következő index.js fájlt hoztam létre a src/js mappában. Itt végighaladok a sorozatszámok tömbjén, és nullákkal előzöm meg őket, hogy nyolc karakteres karakterláncot alkossak belőlük. Később ezt fogjuk felhasználni, és egy HTML-oldalon egy rendezett listaelembe tesszük ki őket. Vegyük észre, hogy ez a példa az alapértelmezett export szintaxist használja:

Mint korábban tettük, futtassuk a build scriptet a <ROOT> könyvtárból:

npm run build

A Babel most létrehoz egy index.js fájlt a public/js könyvtárban. A leftPad.js fájlunkhoz hasonlóan látnod kell, hogy a Babel lecserélte az összes ES6 szintaxist, és csak ES5 szintaxist hagyott hátra. Azt is észreveheted, hogy az ES6 modul szintaxisát a Node-alapú module.exports-ra alakította át, ami azt jelenti, hogy a parancssorból is futtathatjuk:

node public/js/index.js// 

A terminálodnak most ki kell adnia egy tömbnyi, nullával előtagolt karakterláncot, hogy mind nyolc karakter hosszú legyen. Ha ezzel megvagyunk, ideje megnézni a webpacket.

A webpack bemutatása és integrálása a Babelbe

Amint említettük, az ES6 modulok lehetővé teszik a JavaScript-fejlesztő számára, hogy a kódját kezelhető darabokra bontsa, de ennek az a következménye, hogy ezeket a darabokat fel kell szolgálni a kérő böngészőnek, ami potenciálisan további több tucatnyi HTTP-kérést adhat vissza a szervernek – amit igazán el kellene kerülnünk. Itt jön a képbe a webpack.

A webpack egy modulcsomagoló. Elsődleges célja, hogy feldolgozza az alkalmazásodat az összes függőségének felkutatásával, majd az összeset egy vagy több csomagba csomagolja, amelyek a böngészőben futtathatók. Azonban ennél sokkal több is lehet, attól függően, hogy hogyan konfiguráljuk.

Awebpack konfigurációja négy fő komponens köré épül:

  • egy belépési pont
  • egy kimeneti hely
  • betöltők
  • pluginok

Belépés:

Kimeneti hely: Ez tartalmazza az alkalmazásod kezdőpontját, ahonnan a webpack azonosítani tudja a függőségeit.

Kimeneti hely: Ez adja meg, hogy a feldolgozott csomagot hova szeretné menteni.

Loaders: Ezek egy módja annak, hogy egy dolgot bemenetként átalakítsunk, és valami mást generáljunk kimenetként. Használhatók a webpack képességeinek kiterjesztésére, hogy ne csak JavaScript fájlokat kezeljen, és így azokat is érvényes modulokká konvertálja.

Plugins: Ezeket arra használjuk, hogy a webpack képességeit a csomagoláson túl más feladatokra is kiterjesszük – például minifikálásra, lintingre és optimalizálásra.

A webpack telepítéséhez futtassuk a következőt a <ROOT> könyvtárból:

npm install webpack webpack-cli --save-dev

Ez a webpacket lokálisan telepíti a projektbe, és a webpack-cli hozzáadásával a webpack parancssorból történő futtatására is lehetőséget ad. Most már látnod kell, hogy a webpack a package.json fájlban szerepel. Ha már ebben a fájlban vagy, módosítsd a szkriptek részt az alábbiak szerint, hogy most már tudja, hogy a Babel helyett közvetlenül a webpackot használja:

"scripts": { "build": "webpack --config webpack.config.js"},

Amint látod, ez a szkript egy webpack.config.js fájlt hív, ezért hozzuk létre azt a <ROOT> könyvtárunkban a következő tartalommal:

Ez nagyjából a legegyszerűbb konfigurációs fájl, amire a webpackkel szükséged van. Láthatjuk, hogy a korábban ismertetett entry és output részeket használja (ezekkel önmagában is működhetne), de tartalmaz egy mode: 'development' beállítást is.

A webpacknek lehetősége van arra, hogy “development” vagy “production” módot használjon. A mode: 'development' beállítás a build sebességére és a hibakeresésre optimalizál, míg a mode: 'production' a futásidejű végrehajtás sebességére és a kimeneti fájl méretére. Tobias Koppers “webpack 4: mode and optimization” című cikkében található egy jó magyarázat a módokról, ha többet szeretne olvasni arról, hogyan lehet ezeket az alapértelmezett beállításokon túl konfigurálni.

A következő lépésben távolítson el minden fájlt a public/js mappából. Ezután futtasd újra ezt:

npm run build

Meglátod, hogy most már egyetlen ./public/bundle.js fájlt tartalmaz. Ha azonban megnyitjuk az új fájlt, a két fájl, amellyel kezdtük, meglehetősen másképp néz ki. Ez a fájlnak az a része, amely a index.js kódot tartalmazza. Annak ellenére, hogy elég erősen megváltozott az eredetihez képest, még mindig kivehetjük a változóneveit:

Ha lefuttatjuk a node public/js/bundle.js parancsot a <ROOT> mappából, láthatjuk, hogy ugyanazt az eredményt kapjuk, mint korábban.

Transpiling

Amint korábban említettük, a betöltők lehetővé teszik számunkra, hogy egy dolgot valami mássá alakítsunk át. Ebben az esetben azt szeretnénk, hogy az ES6-ot ES5-té alakítsuk át. Ehhez szükségünk lesz még néhány csomagra:

npm install babel-loader babel-core --save-dev

Használatukhoz a webpack.config.js-nek szüksége van egy modul szakasz hozzáadására a kimeneti szakasz után, így:

Ez egy regex utasítással azonosítja a babel-loader-vel átfordítandó JavaScript fájlokat, miközben kizár mindent, ami a node_modules mappában van, ebből. Végül a babel-loader utasítást kap, hogy használja a korábban telepített babel-preset-env csomagot, hogy létrehozza a .babelrc fájlban beállított transzpilezési paramétereket.

Mivel ez megtörtént, újra lefuttathatja ezt:

npm run build

Aztán ellenőrizze az új public/js/bundle.js-ot, és látni fogja, hogy az ES6 szintaxis minden nyoma eltűnt, de még mindig ugyanazt a kimenetet produkálja, mint korábban.

Bevisszük a böngészőbe

Miután felépítettünk egy működő webpack és Babel beállítást, itt az ideje, hogy a böngészőbe vigyük, amit csináltunk. Egy kis HTML fájlra van szükség, ezt a <ROOT> mappában kell létrehozni az alábbiak szerint:

A lista megjelenítéséhez még egy kis JavaScriptre van szükség, ezért módosítsuk a ./src/js/index.js mappát, hogy ez megtörténjen:

Most, ha megnyitjuk a index.html-t a böngészőben, egy rendezett listát kell látnunk, így:

Továbbfejlesztés

A fenti beállítások szerint a felépítési rendszerünk nagyjából készen áll. Most már használhatjuk a webpacket a moduljaink csomagolására, és a Babel segítségével lefordíthatjuk az ES6 kódot ES5-re.

Az azonban egy kicsit bosszantó, hogy az ES6 kódunk átfordításához minden egyes változtatásnál le kell futtatnunk a npm run build parancsot.

A ‘watch’

Az npm run build ismételt futtatásának szükségességét kiküszöbölhetjük azzal, hogy beállítunk egy 'watch'-t a fájljainkon, és a webpack automatikusan újrafordít minden alkalommal, amikor a ./src mappában lévő fájlok valamelyikében változást lát. Ennek megvalósításához módosítsd a package.json fájl scripts szakaszát az alábbiak szerint:

"scripts": { "watch": "webpack --watch", "build": "webpack --config webpack.config.js"},

Az ellenőrzéshez, hogy működik-e, futtasd a npm run watch-t a terminálból, és látni fogod, hogy már nem tér vissza a parancssorba. Most menj vissza a src/js/index.js-be, és adj hozzá egy extra értéket a serNos tömbhöz, majd mentsd el. Az enyém most így néz ki:

const serNos = ;

Ha most megnézed a terminálban, látni fogod, hogy kijelentkezett, és hogy újra lefuttatta a webpack build feladatot. Ha pedig visszamegy a böngészőbe és frissít, látni fogja, hogy az új érték a lista végére került, miután a leftPad-vel feldolgozta.

A böngésző automatikus frissítése

Igazán jó lenne, ha a webpack minden változtatáskor automatikusan frissítené a böngészőt. Tegyük ezt úgy, hogy telepítünk egy további npm csomagot webpack-dev-server néven. Ne felejtsük el azonban előbb a watch feladatból Ctrl + c-vel kilépni!

npm install webpack-dev-server --save-dev

Mivel ez megtörtént, adjunk hozzá egy új szkriptet a package.json fájlhoz az új csomag meghívásához. A scripts szakasznak most már ezt kell tartalmaznia:

Nézzük meg a szkript végére hozzáadott --open-page jelzőt. Ez azt mondja a webpack-dev-server-nek, hogy nyisson meg egy adott oldalt az alapértelmezett böngészőben, annak iframe módját használva.

Most futtassa a npm start-öt, és látnia kell, hogy egy új böngészőfül nyílik meg a -nél, ahol megjelenik az alkatrészlista. Hogy megmutassa, hogy a 'watch' működik, menjen a src/js/index.js-be, és adjon hozzá egy másik új értéket a serNos tömb végéhez. Amikor elmenti a változtatásokat, szinte azonnal észre kell vennie, hogy azok tükröződnek a böngészőben.

Mivel ez megtörtént, már csak az van hátra, hogy a webpack.config.js-ben a módot production-ra állítsa. Ha ez be van állítva, a webpack a ./public/js/bundle.js-be kiadott kódot is kicsinyíteni fogja. Megjegyzendő, hogy ha a mode nincs beállítva, akkor a webpack alapértelmezés szerint a production konfigurációt fogja használni.

Következtetés

Ebben a cikkben láthattad, hogyan állíthatod be a modern JavaScript építési rendszerét. Kezdetben ez a Babel-t használta a parancssorból az ES6 szintaxis ES5-re való lekonvertálásához. Ezután láthattad, hogyan használhatod az ES6 modulokat a export és import kulcsszavakkal, hogyan integrálhatod a webpacket a csomagolási feladat elvégzéséhez, és hogyan adhatsz hozzá egy watch feladatot, hogy automatizáld a webpack futtatását minden egyes alkalommal, amikor egy forrásfájl változását észleled. Végül láthattad, hogyan telepítheted a webpack-dev-server-t, hogy automatikusan frissítse az oldalt minden egyes módosításkor.

Ha tovább szeretnéd folytatni ezt a témát, javaslom, hogy olvasd el a SitePoint mély merülését a webpack és a modulkötegelés témájában, valamint kutass további betöltők és bővítmények után, amelyek lehetővé teszik, hogy a webpack kezelje a Sass és az eszköztömörítési feladatokat. Szintén nézd meg a eslint-loader és a Prettier plugin-t is.

Boldog csomagolást …