Czy są jakieś biblioteki dla javascript w przeglądarce, które zapewniają taką samą elastyczność / modułowość / łatwość użycia jak Node require
?
Mówiąc bardziej szczegółowo: powód require
jest tak dobry, że:
- Umożliwia dynamiczne ładowanie kodu z innych lokalizacji (co moim zdaniem jest lepsze stylistycznie niż łączenie całego kodu w HTML)
- Zapewnia spójny interfejs do budowania modułów
- Moduły łatwo zależą od innych modułów (więc mógłbym napisać na przykład API, które wymaga jQuery, abym mógł używać
jQuery.ajax()
- Załadowany javascript ma określony zakres , co oznacza, że mógłbym załadować
var dsp = require("dsp.js");
i byłbym w stanie uzyskać dostępdsp.FFT
, co nie kolidowałoby z moim lokalnymvar FFT
Nie znalazłem jeszcze biblioteki, która robi to skutecznie. Rozwiązania, których zwykle używam, to:
coffeescript-concat - dość łatwo jest wymagać innego js, ale musisz go skompilować, co oznacza, że jest mniej świetny do szybkiego programowania (np. budowanie API w testach)
RequireJS - Jest popularny, prosty i rozwiązuje 1-3, ale brak zakresu jest prawdziwym przełomem (uważam, że head.js jest podobny, ponieważ brakuje mu zakresu, chociaż nigdy nie miałem okazji go użyć. Podobnie LABjs może ładować i łagodzić
.wait()
problemy z zależnościami, ale nadal nie obsługuje zakresu)
O ile wiem, wydaje się, że istnieje wiele rozwiązań dla dynamicznego i / lub asynchronicznego ładowania javascript, ale mają one te same problemy z zakresem, co samo ładowanie js z HTML. Bardziej niż cokolwiek innego, chciałbym mieć sposób na załadowanie javascript, który w ogóle nie zanieczyszcza globalnej przestrzeni nazw, ale nadal pozwala mi ładować i używać bibliotek (tak jak wymaga tego węzeł).
AKTUALIZACJA 2020: Moduły są teraz standardem w ES6, a od połowy 2020 roku są natywnie obsługiwane przez większość przeglądarek . Moduły obsługują ładowanie synchroniczne i asynchroniczne (przy użyciu Promise). Obecnie zalecam, aby większość nowych projektów korzystała z modułów ES6 i transpilera w celu powrotu do pojedynczego pliku JS dla starszych przeglądarek.
Zgodnie z ogólną zasadą, dzisiejsza przepustowość jest zwykle znacznie szersza niż wtedy, gdy zadawałem to pytanie. Tak więc w praktyce możesz rozsądnie zdecydować się zawsze używać transpilera z modułami ES6 i skupić się na wydajności kodu, a nie na sieci.
POPRZEDNIA EDYCJA (lub jeśli nie lubisz modułów ES6): Od czasu napisania tego, intensywnie korzystałem z RequireJS (który ma teraz znacznie bardziej przejrzystą dokumentację). Moim zdaniem RequireJS był naprawdę trafnym wyborem. Chciałbym wyjaśnić, jak ten system działa dla ludzi, którzy są tak zdezorientowani jak ja:
Możesz używać require
w codziennym rozwoju. Moduł może być czymkolwiek zwracanym przez funkcję (zazwyczaj jest to obiekt lub funkcja) i jest objęty zakresem jako parametr. Możesz także skompilować swój projekt w jednym pliku do wdrożenia przy użyciu r.js
(w praktyce jest to prawie zawsze szybsze, mimo że require
można równolegle ładować skrypty).
Podstawową różnicą między RequireJS a stylem węzłów, których używa browserify (fajny projekt sugerowany przez tjameson), jest sposób, w jaki moduły są projektowane i wymagane:
- RequireJS używa AMD (Async Module Definition). W AMD
require
pobiera listę modułów (pliki javascript) do załadowania i funkcję wywołania zwrotnego. Po załadowaniu każdego z modułów wywołuje wywołanie zwrotne z każdym modułem jako parametr funkcji zwrotnej. Dzięki temu jest naprawdę asynchroniczny i dlatego dobrze nadaje się do sieci. - Węzeł używa CommonJS. W CommonJS
require
jest to wywołanie blokujące, które ładuje moduł i zwraca go jako obiekt. Działa to dobrze w przypadku Node, ponieważ pliki są odczytywane z systemu plików, co jest wystarczająco szybkie, ale działa słabo w Internecie, ponieważ synchroniczne ładowanie plików może zająć znacznie więcej czasu.
W praktyce wielu programistów korzystało z Node (a tym samym z CommonJS), zanim kiedykolwiek zobaczyli AMD. Ponadto wiele bibliotek / modułów jest napisanych dla CommonJS (przez dodanie rzeczy do exports
obiektu), a nie dla AMD (przez zwrócenie modułu z define
funkcji). Dlatego wielu deweloperów korzystających z Node chce korzystać z bibliotek CommonJS w sieci. Jest to możliwe, ponieważ ładowanie z <script>
tagu jest blokowane. Rozwiązania takie jak browserify pobierają moduły CommonJS (Node) i opakowują je, aby można było dołączyć je do tagów skryptów.
Dlatego też, jeśli tworzysz swój własny, wieloplikowy projekt dla sieci, zdecydowanie polecam RequireJS, ponieważ jest to naprawdę modułowy system dla sieci (choć, uczciwie mówiąc, uważam, że AMD jest o wiele bardziej naturalne niż CommonJS). Ostatnio to rozróżnienie straciło na znaczeniu, ponieważ RequireJS pozwala teraz zasadniczo używać składni CommonJS. Dodatkowo, RequireJS może służyć do ładowania modułów AMD w Node (chociaż wolę node-amd-loader ).