W Node.js każdy plik jest traktowany jako osobny moduł, a iż nie piszemy całej aplikacji w jednym pliku to musimy w jakiś sposób nimi zarządzać. Do tej pory w środowisku Node.js korzystaliśmy z modułów CommonJS ale to się może zmienić w przyszłości kiedy stabilne będą moduły ECMAScript.
Moduły CommonJS
Z tymi modułami zetknął się każdy kto chodź raz pisał jakiś skrypt w Node.js. Do zaimportowania zewnętrznego modułu wykorzystujemy składnię reqiure. Natomiast aby udostępnić jakieś funkcje czy wartości dla innych modułów mamy module.exports lub exports
Zastanawialiście się kiedyś jak to działa? Skąd się bierze metoda require i obiekt module? Idea mechanizmu jest prosta w przeciwieństwie do implementacji (jeśli ktoś ma chwilę wolnego czasu to może zerknąć do repozytorium). Każdy moduł, który używamy w naszej aplikacji jest opakowywany w funkcję
Nasz moduł wygląda wtedy następująco:
Dzięki temu, w taki trochę magiczny i ukryty sposób, możemy eksportować i importować moduły w CommonJS.
Moduły ECMAScript
To po co nam adekwatnie inny sposób radzenia sobie z modułami? Po co nam nowy mechanizm skoro stary się sprawował dobrze przez tyle lat? Ponieważ tak naprawdę to moduły ECMAScript są oficjalnym sposobem na radzenie sobie z modułami w JS'ie. Dzięki temu, iż zostały wprowadzone to mamy to zunifikowane dla JS'a i możemy tworzyć biblioteki, które będą z tego mechanizmu korzystały w każdym miejscu gdzie możemy użyć języka JavaScript.
Jak teraz będzie wyglądało korzystanie z innych modułów? Mamy tutaj składnię, którą kojarzymy np.: z React'a czyli import i export
Oczywiście nie możemy od razu z tego skorzystać gdyż jest to ciągle funkcjonalność eksperymentalna. Na szczęście nie musimy też jej włączać żadnymi flagami gdyż jest domyślnie włączona. Aby skorzystać z tej funkcjonalności mamy dwie drogi:
- W pliku package.json dołożyć wpis "type": "module"
- Użyć rozszerzenia *.mjs zamiast *.js do plików
Top-level await
Jest jeszcze jedna zaleta korzystania z modułów ECMAScript. Od jakiegoś czasu w najnowszej wersji Node'a jest dla tych modułów uruchomiony top-level await. Dzięki temu nie musimy opakowywać naszego kodu w IIFE (Immediately-invoked function expression) tylko możemy skorzystać z await bezpośrednio
W przypadku Node'a jest to o tyle wygodne, iż wiele rzeczy dzieje się asynchronicznie a na które potrzebujemy czekać np.: nawiązanie połączenia z bazą danych żeby wystartować resztę aplikacji. Jednak aby włączyć tę funkcjonalność musimy ją jeszcze aktywować przy pomocy flagi
A wy co sądzicie o nowych modułach i top-level await? Korzystaliście już z tego czy czekacie aż będzie to rozwiązanie stabilne? Myślicie, iż zmieni to sposób w jaki tworzymy aplikacje?