Obecnie specjaliści od frontendu mają możliwość korzystania z wielu systemów automatyzacji, które przyspieszają i ułatwiają pracę. Gulp, Grunt, Browserify, Brunch, Commonjs, Webpack – to podstawowe narzędzia, których codziennie używają miliony developerów na świecie.
Jak to mówią – dobry programista powinien być z natury leniwy – jeśli będzie musiał coś zrobić więcej niż raz, to w końcu napisze skrypt, który zrobi to za niego, co w efekcie przyspieszy prace.
Dlaczego więc nie używać narzędzi, które ktoś zrobił za nas i które dostarczą nam szereg gotowych rozwiązań automatyzujących rzeczy, które robimy na co dzień?
Koniec z szukaniem kodu, jego pobieraniem, kopiowaniem i dodawaniem kolejnych wpisów script i link w html.
Dlaczego Webpack?
1. W skrócie – łatwa konfiguracja oraz dużo gotowych rozwiązań.
Twórcy Webpacka oraz niezależni programiści dbają o to aby dostarczyć nam gotowe loadery i pluginy, które możemy łatwo zainstalować z użyciem npm oraz łatwo skonfigurować dodając wpis w pliku konfiguracyjnym.
2. Zarządzanie zależnościami.
Każdy kto programuje w JavaScript w wersji starszej niż ES6, wie jak ciężko jest tworzyć ‘’ładny” kod, zachować w nim porządek oraz wstrzykiwać zależności, choćby takie jak jQuery czy twBootstrap.
Webpack upraszcza nam to wszystko.
Przykład z jQuery:
Instalacja przez konsolę:
npm install jquery
Załadowanie zależności w kodzie:
var $ = require(‘jquery’) ;
Szybko i łatwo – bez szukania kodu, jego pobierania, kopiowania i dodawania czegokolwiek w html, a kiedy dodamy tutaj możliwość ładowania w taki sposób obrazów, czcionek, stylów to mamy rozwiązanie kompleksowe.
Jak działa Webpack?
Zadaniem Webpacka jest wychwycenie zależności w projekcie i stworzenie dla nich statycznych „paczek” z kodem, które potem są ładowane na żądanie. Wszystkie zależności definiowane poprzez require() lub import są grupowane (co zapobiega duplikowaniu) i m.in. składane w jeden plik lub kopiowane w inne miejsce.
Jako moduł jest traktowany każdy plik – js, css, sass, txt, jpg, html etc.
Po tym jak zależności są załadowane możemy je przetwarzać, co daje nam nieograniczone możliwości co się stanie z danymi, które są w nich zawarte lub z całymi plikami.
W tym celu używa się loaderów i pluginów.
Loader – pozwalają przetwarzać pliki zanim zostaną z nich utworzone moduły i połączone w jeden plik. Możemy np. przetwarzać sass na css, es6 na es5, kopiować fonty i obrazy lub inne pliki.
Plugin – pozwalają nam one na ingerowanie w proces budowania aplikacji na każdym jego etapie (przed utworzeniem modułu, po jego utworzeniu itd).
Przykłady. W tej częsci omówimy podstawowe użycie.
Wymagane jest od nas zainstalowanie nodejs oraz npm.
1. Inicjujemy nowy projekt i uzupełniamy informacje, o które jesteśmy pytani
npm init
Zostanie wtedy utworzony plik package.json, gdzie będą trzymane m.in. informacje o tym jakich paczek używamy oraz skrypty, czyli pewnego rodzaju aliasy.
2. Instalacja i konfiguracja
Instalujemy globalnie
npm install webpack -g
Dodajemy do zależności w naszym projekcie jako paczkę do celów developerskich –save-dev
npm install webpack –save-dev
Tworzymy plik konfiguracyjny:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
module.exports = { entry: './src/app.js', output: { path: __dirname, filename: 'dist/bundle.js' } }; |
Prosta konfiguracja, która pozwala nam na razie tylko na wstrzykiwanie zależności.
Zobaczmy co się stanie kiedy zainstalujemy i załadujemy jQuery.
Konsola:npm install jquery –save
app.js
var $ = require(‘jquery’);
Uruchamiamy webpack wpisując w konsolę:
webpack
jQuery zostanie dodane do listy zależności w package.json a kod zostanie połączony w jeden plik w bundle.js
Prawda, że proste i przyjemne?
Teraz zobaczmy jak możemy wykorzystać to praktycznie.
Lepszym podejściem niż ładowanie globalnie zależności w pliku entry, jest ładowanie jej tam gdzie mamy zamiar jej użyć. Pozwala nam to lepiej zorganizować kod i daje obraz – co jest używane do działania danego komponentu/modułu.
Spróbujmy stworzyć usługę, która będzie pozwalała wysłać formularze z wykorzystaniem ajaxa.
Tworzymy katalog services, a w nim dwa pliki index.js w którym będziemy ładować wszystkie usługi oraz AjaxForm.js w którym będzie znajdowała się nasza klasa do wysiłki formularzy.
W app.js ładujemy wszystkie usługi odwołując się do pliku index.js w katalogu services.
(Jeśli ładujemy nasze lokalne moduły to musimy używać ścieżek względnych. Podanie samej nazwy typu require(‘AjaxForm’) spowoduje, że webpack będzie szukał w node_modules. Można, co prawda zdefiniować to w pliku konfiguracyjnym, ale jest to temat na kolejny wpis. Powinniśmy zatem odwołać się w taki sposób – require(‘./AjaxForm’))
Kod wygląda w ten sposób:
AjaxForm.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
var $ = require('jquery'); module.exports = (function () { /** * AjaxForm class to send a form via ajax * * @param $form * @constructor */ function AjaxForm ($form) { this.form = $form; } /** * Get send method * * @returns {*|string|string} * @private */ AjaxForm.prototype._method = function () { return this.form.method || 'post'; }; /** * Get the url for send * * @returns {string|string} * @private */ AjaxForm.prototype._url = function () { return this.form.action || ''; }; /** * Get the form data * * @returns {*} * @private */ AjaxForm.prototype._data = function () { return new FormData(this.form); }; /** * Run the send process * * @returns {*} */ AjaxForm.prototype.send = function () { return $.ajax(this._url(), { method: this._method(), data: this._data(), processData: false }); }; return AjaxForm; })(); |
index.js w services
1 2 3 4 5 |
module.exports = { ajaxForm: require('./AjaxForm') }; |
app.js (webpack entry)
1 |
window.services = require('./services'); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
Użycie: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Webpack sample</title> <script src="./bundle.js"></script> </head> <body> <script> <b>var </b>onSubmit = <b>function </b>($e, $form) { $e.preventDefault(); <b>var </b>ajaxForm = <b>new </b>services.ajaxForm($form); ajaxForm.send(); } </script> <form onsubmit="onSubmit(event, <b>this</b>)" action="test.php" method="post"> <input type="text" name="name"> <input type="submit" value="Submit"> </form> </body> </html> |
W łatwy i prosty sposób mogliśmy zorganizować nasz kod, mając w pełni kontrolę co i gdzie jest ładowane. Możemy wtedy m.in. łatwo odnaleźć używany kod i zapanować nad jego strukturą.
W następnym artykule pokażemy jak można jeszcze bardziej ‘upiększyć’ nasz kod, dodając babel-loader i ES6.
Warto zapoznać się jeszcze z:
Użycie es6 oraz watch i dodawanie skryptu w package.json z wykorzystaniem powyższego przykładu.
Style, kopiowanie plików graficznych i czcionek (przykład z bootstrap) z wykorzystaniem powyższego przykładu.