JavaScript jest językiem interpretowanym, nie potrzebuje kompilacji. Twoja przeglądarka wykonuje ten sam kod, który piszesz. Po co więc stosować bundlery JavaScript?
Mniej plików JS
Swego czasu liczba plików JS wykorzystywanych przez witrynę internetową była kluczową sprawą, ponieważ duża liczba takich plików o niewielkim rozmiarze powodowała spadki wydajności. Przeglądarki ładowały każdy plik na podstawie odrębnego żądania HTTP. Każde żądanie wymagało połączenia między przeglądarką a serwerem, a to za każdym razem zajmowało nieco czasu. Aktualnie, dzięki protokołowi HTTP/2, liczba plików nie tworzy już takich problemów. Nadal jednak pakowanie plików razem ma sens. Każde żądanie jest zapisywane osobno w pamięci podręcznej, więc duża liczba plików sprawia, iż trudniej jest zapewnić, że przeglądarka nie załaduje z tej pamięci nieodświeżonego kodu.
Poza tym do 2018 roku wiele przeglądarek nie obsługiwało modułów ES. Ładowało się wiele plików z HTML i wszystkie dzieliły zakres globalny. Bundlery JS rozwiązują oba problemy, ponieważ:
- pozwalają na przechowywanie bazy kodu podzielonej na wiele dobrze zorganizowanych plików,
- pakują kod w duże pliki do wrzucenia na serwer.
Prosty import z node_modules
Bundlery dają Ci możliwość importowania zależności, co jest dużo wygodniejsze niż ładowanie ich jako modułów ES. Aby wykorzystać pakiety węzłów otrzymane z przeglądarki, musiałbyś:
- opublikować
node_modules
na serwerze produkcyjnym, - zastosować ścieżkę względną od Twojego pliku do pliku, który chcesz importować.
Stosowanie ścieżki względnej jest problematyczne, bo zmusza Cię to do pisania importu na nieco różne sposoby, w zależności od tego, jak głęboko w strukturze folderowej akurat się znajdujesz. W przypadku Lodash będziesz mieć coś takiego:
// in ./src/core.js
var _ = require('../node_modules/lodash/lodash.js');
// in ./src/app/main.js
var _ = require('../../node_modules/lodash/lodash.js');
Bundlery pozwolą Ci na uzyskanie tego samego prościej:
// anywhere
var _ = require('lodash');
Import innych rodzajów plików
Twoja baza kodu składa się nie tylko z JavaScript. Jeżeli porządkujesz swój kod według komponentów lub ścieżek, każdy taki element będzie mieć swój własny szablon i swoją własną stylizację. Natywne moduły ES nie pozwalają na importowanie typów zasobów innych niż JS. Przez to ograniczenie byłbyś zmuszony zaimportować CSS z HTML, ale reszta byłaby importowana w JavaScript – co sprawiłoby, że musiałbyś zsynchronizować dwa niezwiązane ze sobą pliki. Bundlery JS obchodzą ten problem, pozwalając Ci zarządzać wszystkimi zależnościami bezpośrednio z Twoich plików JS:
import ‘./core.js’;
import ‘./style.css’;
const template = require(‘./view.html’);
Transpilacja kodu
Duża część JavaScript to tak naprawdę nie tylko JavaScript: jest on pisany w językach takich jak TypeScript, a następnie kompiluje się go do JavaScript. Taka kompilacja z jednego kodu do drugiego nazywa się transpilacją. Poddawana jest jej większość kodu pisanego w JavaScript. Poniżej tłumaczę, dlaczego tak jest.
Minifikacja kodu
Jeśli piszesz swój kod tak, jak trzeba, to:
- nadajesz zmiennym sensowne nazwy,
- stosujesz wcięcia,
- zostawiasz komentarze dla pozostałych programistów.
To wszystko to tylko szum, który dla interpretera nie znaczy zupełnie nic. Minifikacja jest pierwszym krokiem na drodze redukcji rozmiaru payload. Usuwa wszystko, co nie ma wpływu na działanie aplikacji.
Downgrade do starszych wersji przeglądarek
Kiedy kod poszerza wachlarz swoich funkcji, w pewnym momencie dochodzi do sytuacji, w której:
- developerzy chcą zacząć już z niego korzystać,
- nie jest on obsługiwany przez wszystkie przeglądarki.
Na szczęście sytuacja taka utrzymuje się już znacznie krócej dzięki przeglądarkom typu evergreen, ale nadal istnieje zapotrzebowanie na projekty pokroju Babel. Kompilator ten pozwala Ci na korzystanie z najnowszej wersji języka podczas kodowania i na transpilowanie kodu do wersji obsługiwanej przez starszą wersję przeglądarki.
Odmiany JavaScript
Obok standardowego JavaScript możesz korzystać z wielu jego odmian:
- TypeScript,
- PureScript,
- Elm,
- CoffeeScript.
Bundlery JavaScript radzą sobie z jednolitym mieszaniem różnych odmian w jednym projekcie – co wydaje się kiepskim pomysłem dopóty, dopóki nie zaczniesz pracować z przestarzałym kodem i dopóki nie będziesz potrzebować dużej dozy elastyczności, żeby wybrać odpowiednie priorytety.
Osobne buildy dla różnych przypadków użycia
Kiedy zaczniesz już kompilować swój kod bundlerem, otworzą się przed Tobą nowe możliwości. Najpewniej od samego początku kompilujesz kod w jeden sposób na potrzeby środowiska produkcyjnego, a inny na potrzeby programowania lokalnego. Jeśli piszesz testy jednostkowe, możesz być ciekaw, jak dobrze weryfikują one Twój kod. Istnieją narzędzia, które dadzą Ci dokładną odpowiedź na to pytanie – są to tzw. narzędzia mierzące pokrycie kodu. Wymagają one dedykowanego buildu obejmującego narzędzia zliczające, ile razy test podczas wykonywania „odwiedza” daną linię kodu.
A co z Tobą?
Z jakiego bundlera JS chcesz skorzystać w ramach swojego kolejnego projektu? Daj mi znać w ankiecie, żebym wiedział, na czym skupić się tutaj w przyszłości:
Co dalej?
Możesz przeczytać mój artykuł o tym, jak korzystać z natywnych modułów ES, lub obejrzeć jeden z moich wideokursów:
- [wideokurs na temat esbuild] (bit.ly/esbuild-course),
- [wideokurs na temat webpack] (bit.ly/esbuild-course).