Tacsiazuma
Tacsiazuma A letscode.hu alapitója, több, mint egy évtized fejlesztői tapasztalattal. Neovim függő hobbi pilóta.

Javaspricc pakk 2 – Babel

Javaspricc pakk 2 – Babel

Az előző cikkemben szó volt az ECMAScript 6 újításairól. Itt kitértem arra is, hogy azért nem szabad rögtön fejest ugrani a dologba, lévén a böngészők támogatottsága elég vegyes. Viszont az előző szabványra már felkészültek. Emlékezzünk csak vissza a cikkre.. a legtöbb újításra volt valami megfelelő a régiben is, még ha patkolás kategóriába is esett. Nem lehetne megoldani, hogy megírom az újban és visszafelé kompatibilissá teszem?

Hát hogy a gránátba ne!?[![Pieter_Bruegel_the_Elder_-The_Tower_of_Babel(Vienna)-_Google_Art_Project-edited](assets/uploads/2015/12/Pieter_Bruegel_the_Elder-The_Tower_of_Babel_Vienna-Google_Art_Project-edited.jpg)](assets/uploads/2015/12/Pieter_Bruegel_the_Elder-The_Tower_of_Babel_Vienna-Google_Art_Project-_edited.jpg)

Ahhoz, hogy nekikezdhessünk a dolognak, először is szükségünk lesz a babelre, valamilyen formában. Két opció van, az egyik csak backendre illeszthető, ún. require-hook, ami annyit tesz, hogy a node.js által behúzott fájlokat leforgatja. A másik, ami nekünk a frontenden is jó lesz, az a CLI tool, amivel parancssorból lehet átforgatni fájlokat.

Babel-CLI

A babelhez mindenképp szükségünk lesz egy node/npm kombóra a gépünkön.

Utána tudjuk telepíteni is:

1
npm install --save-dev babel-cli

Ezzel bármelyik projektünkbe tudjuk telepíteni azt.

Nem érdemes globálisan telepíteni, lévén a szabvány különböző elemeit konfigurálni kell és ezek csúnyán összeakadhatnak a projektek közt

Ha ezzel megvolnánk, akkor elméletben már készen is állunk arra, hogy leforgassunk egy kódrészletet.

A parancssori tool viszonylag egyszerűen kezelhető.

Hozzunk is létre a projektünkben egy src és egy dist mappát. Ez előbbi tartalmazza majd az ES6-os forrást, míg az utóbbiba kerülnek majd a lefordított és minifikált fájlok. Akkor csináljunk egy post.js-t, amiben a legfincsibb újdonságok egyikét fogjuk kipróbálni, mégpedig a class definitiont:

1
2
3
4
5
6
7
class Post {
   constructor(title, content, slug) {
      this.title = title;
      this.content = content;
      this.slug = slug;
   }   
}

Akkor most nézzük meg, hogy működik-e a cucc:

1
babel src -d dist

A fenti parancs az src mappában található scripteket a dist mappába forgatja le. Adjuk hát ki a parancsot és nézzük meg a kimenetet!

Ő… ez tök ugyanaz. Valami gond van? Na jó.. valami gond van.fullretard

A korábbiakban említettem, hogy a fordítót konfigurálni kell, ez pedig az egyes szintaktikákra vonatkozik, mert nem csak ES6-ról es ES5-re lehet alakítani a dolgot, hanem többféle szintax közti átjárást biztosít, akár csak a szintax egyes részeire vonatkozólag is. Ezeket ún. pluginekkel tudjuk lehetővé tenni, amiből a babel 6-os verziójáig a legtöbb default be volt kapcsolva. Viszont mostantól nekünk kell ezeket bekapcsolni.

.babelrc

Hozzuk hát létre a .babelrc fájlt a projektünk gyökerében. Ez egy szimpla JSON formátumú fájl, hasonló a package.json-höz.

1
2
3
4
5
6
7
{
 "plugins": ["transform-react-jsx"], // a plugineket itt lehet megadni
 "ignore": [ // ignore listre tehetünk bizonyos fájlokat, amiket nem forgat át a rendszer
 "foo.js",
 "bar/**/*.js"
 ]
}

Sőt, akár a package.json-be is beágyazhatjuk a .babelrc konfigurációját:

1
2
3
4
5
6
{
 "name" : "Babel-teszt",
 "version" : "1.0.0",
 "babel" : {
      // a babelrc tartalma
   }
1
}

Na de akkor mostmár nem ártana dologra fogni a cuccot, nemde? Mivel mi ES6-ról szeretnénk ES5-re alakítani, telepítsünk hozzá plugineket:

1
npm install babel-plugin-syntax-constructor-call

Figyelem: a fenti plugin csak annyit tesz lehetővé, hogy a babel felismerje az új constructor syntax-ot, viszont azt nem tudja hogy is kellene átalakítani azt

Mivel elég sok újdonság jött a nyelvvel, ezért jobban járunk, ha ún. presetet telepítünk, amiben összecsomagolva ott vannak a nekünk szükséges parser/transform pluginek:

1
npm install babel-preset-es2015

Ez ugye csak elérhetővé teszi a preset-et, viszont meg kell mondjuk a babelnek, hogy bizony használja is azt, a package.json-ben (vagy .babelrc fájlban):

1
2
3
4
5
{
   "babel" : {
       "presets" : ["es2015"]
    }
}

Ha ezzel megvolnánk, akkor elvileg minden készen áll a magicre, adjuk ki hát ismét a parancsot:

1
babel src -d dist

Most némileg tovább szüttyög a fordítás, és ennek meg is lesz a gyümölcse! Nézzük meg a leforgatott fájl tartalmát:

1
2
3
4
5
6
7
8
9
10
11
"use strict"; // strict mode on

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } // definiál egy ún. ellenőrző függvényt, amivel meggátoljuk, hogy a konstruktor függvényünket sima függvényként hívjuk meg, a new kulcsszó használata nélkül.

var Post = function Post(title, content, slug) { // az ősi "konstruktor" definíció
 _classCallCheck(this, Post); // itt ellenőrízzük is a dolgot

 this.title = title;
 this.content = content;
 this.slug = slug;
};

Ez utóbbi kódban már nem lesz olyan syntax, amit ne tudna megemészteni a legtöbb böngésző, így ezzel meg is volnánk. Na de mégis hogy is kellene mindezt alkalmazni? Ugye a fejlesztés alatt mi lehetőleg olyan böngészővel fogunk dolgozni, ami támogatja már az újabb syntaxokat is, így ez inkább a production build folyamat során kellene lefusson.

Aki PHPStormot használ, ne fusson bele abba a hibába, hogy egy sima filewatchernek felveszi a babelt, mert megeszi a gépét reggelire 🙂

Akkor nézzük a legegyszerűbb módszert erre. Az első ilyen egy sima package.json-be suvasztott script lesz.

1
2
3
4
5
{
 "scripts" : { // a package.json-ben lehet az adott projektre specifikus scripteket felvenni, amiket az npm-el tudunk majd futtatni
    "build" : "babel src -d dist" // a parancs a kulcs, ami pedig lefut az az értékben lesz, tehát az npm run build-re fog hallgatni
   }
}

Persze tovább is lehet mindezt piszkálni, mert szeretnénk ha az output pl. kommentektől mentes legyen:

1
babel src -d dist --no-comments

Valamint tuningoljuk tovább a dolgot egy kis minifikálással:

1
babel src -d dist --no-comments --minified

Ez se volt túl bonyolult nem? Akkor most nézzük meg az egyik népszerű task runnerrel/build systemmel is:

GruntGrunt

A grunthoz is lehet babel plugint szerezni, ami a build folyamat során hasznunkra lehet:

1
npm install --save-dev grunt-babel

Ezzel megszereztük a babel plugint az adott projektre. Persze szükség van még lokálisan egy gruntra és globálisan a grunt-cli-re is.

Na de nézzük, mit is kell beleoktrojálnunk a gruntfile-unkba?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
module.exports = function(grunt) { // a wrapper function
 require("load-grunt-tasks")(grunt); 

 grunt.initConfig({ 
    "babel": { // a babel related konfiguráció
        options: {
          sourceMap: true
        },
        dist: { // a fájlokra vonatkozó konfig
           files: { 
            "dist/post.js": "src/post.js" // a dist/post.js fájlt az src/post.js fájlból fogja forgatni
           }
        }
    }
 });

 grunt.registerTask("default", ["babel"]); // majd beregisztráljuk a taskot
};

Nézzük, hogy a grunt parancs mit produkál:

1
2
Running "babel:dist" (babel) task
Done, without errors.

futureEzzel meg is volnánk. Remélem sikerült ismét egy lépéssel lendíteni a “jövő” felé.

comments powered by Disqus