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 …