Jak przyspieszyć i usprawnić Node.js bez przechodzenia na Bun
Silniki Bun i Deno na nowo zdefiniowały znane nam środowisko programistyczne JS. Natywna obsługa TypeScriptu, błyskawiczne uruchamianie testów i reaktywny menedżer pakietów wyznaczyły nowy standard jakości. Nie każdy jednak jest gotowy przenieść swoją produkcję na nowe środowisko uruchomieniowe. Specyficzne dodatki C++, niuanse zachowania modułów i nagromadzony kod legacy sprawiają, że większość projektów pozostaje przy klasycznym Node.js.
Zespół projektu Nub postanowił pójść inną drogą. Zamiast tworzyć kolejne izolowane środowisko uruchomieniowe, napisał narzędzie w Rust, które usprawnia standardowego Node.
Na czym polega idea
Projekty programistów często obciążone są tuzinem narzędzi: 4 lub 5 do uruchamiania TypeScriptu, 6 lub 7 do zarządzania wersjami Node.js, 8 do pakietów i 9 do zmiennych środowiskowych. W rezultacie uruchomienie dowolnego skryptu wiąże się z setkami milisekund opóźnienia, zanim kod w ogóle zacznie się wykonywać.
Nub łączy wszystkie te funkcje w jednym pliku binarnym Rust. Narzędzie działa jako przezroczysta warstwa między programistą a Node.js. V8 i standardowe moduły pozostają w środku niezmienione, ale cała otaczająca warstwa narzędziowa działa z wydajnością kodu skompilowanego.
0Uruchamianie TypeScriptu i automatyczny wybór wersji
Polecenie 10 wykonuje formaty 11, 12, 13, 14, 15 i inne bez żadnej konfiguracji narzędzi build.
W środku wykorzystuje szybki parser Oxc napisany w Rust. Do transpilacji i poprawnej resolucji ścieżek (w tym 16 oraz importów bez rozszerzeń) Nub wykorzystuje nowoczesne punkty rozszerzeń Node.js: preload 17 oraz mechanizm 18.
Ciekawe jest również zarządzanie wersjami. Podczas uruchamiania pliku Nub sprawdza pliki 19, 20 lub sekcję 21 w 22. Jeśli wymagana wersja Node nie jest dostępna lokalnie, narzędzie pobiera ją do cache i wykonuje kod przez nią.
1Nub automatycznie usuwa również flagi eksperymentalne dla nowych funkcji Node.js. Praca z 23, 24 lub 25 działa od razu bez konieczności podawania flag CLI.
Przyspieszanie skryptów i uruchamianie binarek
Za każdym razem, gdy wywoływane jest 26 lub 27, uruchamia się pełny proces Node.js tylko po to, aby odczytać 28 i wywołać odpowiedni skrypt powłoki. Oczekiwanie na inicjalizację środowiska JS tworzy zauważalne wąskie gardło.
Ponieważ 29 jest napisane w Rust, nie ma fazy inicjalizacji JavaScript. Skrypty są pobierane natychmiast.
W benchmarkach developerów, gorące uruchomienie skryptu przez 30 trwa około 14 milisekund. Dla porównania, w 31 zajmuje to około 330 milisekund, a 32 przekracza 440 milisekund.
Narzędzie 33 działa podobnie, zastępując 34 i 35. Wywołując binarkę z 36, nie tworzy dodatkowego pośredniego procesu Node.js, co czyni je około 19 razy szybszym niż 37.
2Jeśli pakiet nie jest dostępny lokalnie, 38 pobiera go z rejestru, wykonuje, a następnie usuwa tymczasowo utworzone pliki.
Menedżer pakietów i wsparcie dla Corepack
Polecenie 39 obsługuje pobieranie zależności. Zbudowane jest na silniku Aube, który może pracować w trybie kompatybilności z istniejącymi plikami lock.
Jeśli wchodzisz do projektu z 40, Nub respektuje ustawienia pnpm, odczytuje 41 i buduje graf zależności bez konfliktów. To samo dotyczy projektów z 42 lub 43.
Kilka funkcji bezpieczeństwa podczas instalacji pakietów:
- Automatyczne blokowanie skryptów 44 domyślnie.
- Sprawdzanie wersji pakietów względem bazy danych podatności osv.dev podczas resolucji grafu.
- Minimalne ograniczenie wieku wydania do 24 godzin w celu ochrony przed atakami na łańcuch dostaw.
Do pracy z wieloma wersjami menedżerów pakietów dostępne jest polecenie 45. Tworzy globalne shimy dla 46, 47 i 48. To przydatne zastępstwo dla Corepack, który został usunięty z Node.js począwszy od wersji 25.
Praktyczne użycie
Narzędzie nie wymaga zmiany struktury projektu ani rezygnacji z istniejącej infrastruktury. Możesz zainstalować je globalnie i używać tylko do szybkiego debugowania lub uruchamiania lokalnych narzędzi CLI.
3W pipeline'ach GitHub Actions standardowe 49 jest zastępowane przez 50. Zapewnia to spójny interfejs i przyspiesza wykonywanie kroków build dzięki szybkiemu cache'owaniu i instalacji zależności.
Podsumowanie
Nub okazuje się solidnym kompromisem dla zespołów, które doceniają wygodę Bun, ale napotykają ograniczenia techniczne uniemożliwiające im opuszczenie Node.js. Narzędzie konsoliduje rozproszoną kolekcję narzędzi CLI, przyspiesza codzienne polecenia i nie wymaga przepisania ani jednej linijki kodu.
Projekt jest dość nowy, ale zdążył już zgromadzić około 3,8 tys. gwiazdek na GitHubie. Warto wypróbować przynajmniej dla błyskawicznego wykonywania 51 i wygodnego auto-pobierania wymaganych wersji Node.js.
Powiązane projekty