Czy warto używać Require.js z Angular.js? [Zamknięte]

443

Jestem nowicjuszem w Angular.js i próbuję zrozumieć, czym różni się od Backbone.js ... Kiedyś zarządzaliśmy zależnościami pakietów w Require.js podczas korzystania z Backbone. Czy ma sens robić to samo z Angular.js?

Franck
źródło
Kolejny projekt blogów i nasion: startersquad.com/blog/angularjs-requirejs
iwein
19
Nie - nie używaj wymaganego.j LUB LUB przeglądaj za pomocą Angular.JS po prostu nie ma takiej potrzeby - AngularJS ma system modułowy, a użycie innego systemu modułowego sprawi, że twoje życie będzie niepotrzebnie trudne. Śledziłem odpowiedzi w tym wątku i traciłem zbyt wiele godzin na coś, co było całkowicie niepotrzebne. Przeczytaj ten artykuł, który wyjaśnia, dlaczego nie: medium.com/@dickeyxxx/…
VitalyB
Przeczytaj to, aby zrozumieć różnicę między kątem i wymagaj modułów juristr.com/blog/2014/07/lazy-angular-modules
pilavdzice
1
tutaj jest świetne wideo, które wyjaśnia, dlaczego jest to dobry pomysł i pokazuje, jak używać requestJS z angularJS youtube.com/watch?v=4yulGISBF8w#t=142
gskalinskii
2
@VitalyB Fajny artykuł! Preferuję ładowanie aplikacji na małe kawałki. Wkrótce nic nie będzie kosztować . Cholera, teraz nic mnie to nie kosztuje.
dsign

Odpowiedzi:

224

Tak, sensowne jest używanie angular.jswraz z tym, w require.jsktórym można używać require.jsdo modularyzacji komponentów.

Istnieje projekt seed, który wykorzystuje both angular.js and require.js.

Anshu
źródło
108
Wspomniany wyżej projekt początkowy nie był zmieniany od roku, więc stworzyłem nowy, używając najnowszych AngularJS i RequireJS z pełnym wsparciem dla testowania opartego na testach.
tnajdek
2
@tnajdek, zaktualizowałem link w odpowiedzi Anshu, aby wskazał ten, który sugerujesz.
David Rivers
7
Pamiętaj, że żaden z tych projektów początkowych nie jest zatwierdzony przez zespół Angular. Wymagaj to wzorzec, który miałby więcej sensu w innych kontekstach, a przestawienie go na Angular nie jest, według IMHO, najlepszą praktyką.
XML
2
Książka O'Reilly AngularJS autorstwa Brada Greena i Shyama Seshadri (wydana w kwietniu tego roku) również zaleca dodanie RequireJS na wczesnym etapie rozwoju projektu Angular i dość wyraźnie określa szczegóły.
bjorke
1
Wolałbym robić wszystko podczas kompilacji 1. Browserify.org 2. npmjs.org/package/gulp-angular-filesort
A-Dubb
150

Podsumowując to, co moim zdaniem, pytanie OP naprawdę brzmi:

Jeśli buduję aplikację głównie w Angular 1.x i (domyślnie) robię to w erze Grunt / Gulp / Broccoli i Bower / NPM, i być może mam kilka dodatkowych zależności bibliotek, czy wymaga dodania jasnego, konkretnego wartość ponad to, co otrzymuję, używając Angular bez wymagania?

Lub, mówiąc inaczej:

„Czy waniliowa aplikacja Angular wymaga efektywnego zarządzania podstawowym ładowaniem komponentów Angular, jeśli mam inne sposoby obsługi podstawowego ładowania skryptów?

Uważam, że podstawową odpowiedzią na to jest: „nie, chyba że dzieje się coś innego i / lub nie możesz używać nowszych, bardziej nowoczesnych narzędzi”.

Wyjaśnijmy na wstępie: RequireJS to świetne narzędzie, które rozwiązało niektóre bardzo ważne problemy i zaprowadziło nas na dalszy plan, w kierunku bardziej skalowalnych, bardziej profesjonalnych aplikacji JavaScript. Co ważne, po raz pierwszy wiele osób spotkało się z koncepcją modularyzacji i wyjścia z globalnego zasięgu. Jeśli więc zamierzasz zbudować aplikację Javascript, która wymaga skalowania, to Require i wzorzec AMD nie są złymi narzędziami do tego.

Ale czy jest coś szczególnego w Angular, co sprawia, że ​​Require / AMD jest szczególnie dobrym rozwiązaniem? Nie. W rzeczywistości Angular zapewnia własny wzorzec modularyzacji i enkapsulacji, który na wiele sposobów czyni zbędnymi podstawowe funkcje modularyzacji AMD. Zintegrowanie modułów Angular ze wzorcem AMD nie jest niemożliwe, ale jest trochę ... wybredne. Na pewno będziesz spędzać czas na ładnym zintegrowaniu dwóch wzorców.

Dla pewnej perspektywy samego zespołu Angular, jest to , autorstwa Briana Forda, autora Angular Batarang, a teraz członka głównego zespołu Angular:

Nie polecam używania RequireJS z AngularJS. Chociaż z pewnością jest to możliwe, nie widziałem żadnego przypadku, w którym RequireJS byłby korzystny w praktyce.

Tak więc na bardzo szczegółowe pytanie AngularJS: Angular i Require / AMD są ortogonalne, a miejscami nakładają się. Państwo może używać ich razem, ale nie ma powodu, szczególnie odnoszące się do natury / wzorców samej kątowej.

Ale co z podstawowym zarządzaniem wewnętrznymi i zewnętrznymi zależnościami dla skalowalnych aplikacji Javascript? Czy Require nie robi dla mnie czegoś naprawdę krytycznego?

Polecam sprawdzić Bower i NPM, a zwłaszcza NPM. Nie próbuję rozpoczynać świętej wojny o porównywalne korzyści z tych narzędzi. Chcę tylko powiedzieć: są inne sposoby na skórowanie tego kota, a te sposoby mogą być nawet lepsze niż AMD / Require. (Z pewnością mają znacznie bardziej popularny impet pod koniec 2015 r., Szczególnie NPM, w połączeniu z modułami ES6 lub CommonJS. Zobacz powiązane pytanie SO .)

Co powiesz na leniwe ładowanie?

Pamiętaj, że leniwe ładowanie i leniwe pobieranie są różne. Leniwe ładowanie Angulara nie oznacza, że ​​wyciągasz je bezpośrednio z serwera. W aplikacji w stylu Yeoman z automatyzacją javascript łączymy i minimalizujemy cały shebang razem w jednym pliku. Są obecne, ale nie są wykonywane / tworzone, dopóki nie będą potrzebne. Poprawa prędkości i przepustowości, którą uzyskujesz dzięki temu, znacznie przewyższa wszelkie domniemane ulepszenia wynikające z leniwego pobierania konkretnego kontrolera 20-liniowego. W rzeczywistości zmarnowane opóźnienie sieci i narzut transmisji dla tego kontrolera będzie o rząd wielkości większy niż rozmiar samego kontrolera.

Powiedzmy jednak, że naprawdę potrzebujesz leniwego pobierania, być może w przypadku rzadko używanych elementów aplikacji, takich jak interfejs administratora. To bardzo uzasadniony przypadek. Require może rzeczywiście zrobić to za Ciebie. Ale istnieje również wiele innych , potencjalnie bardziej elastycznych opcji, które pozwalają osiągnąć to samo. I Angular 2.0 najwyraźniej zajmie się tym za nas, wbudowany w router . ( Szczegóły .)

Ale co w trakcie tworzenia mojego lokalnego dewelopera?

Jak mogę załadować wszystkie moje dziesiątki / setki plików skryptowych bez konieczności ręcznego dołączania ich wszystkich do pliku index.html?

Spójrz na pod-generatory w generatorze kątowym Yeomana lub na wzorce automatyzacji zawarte w generatorze-kątowniku lub na standardową automatyzację Webpack dla React. Zapewniają one czysty, skalowalny sposób na: automatyczne dołączanie plików w momencie rusztowania elementów lub po prostu przechwytywanie ich wszystkich automatycznie, jeśli znajdują się w określonych folderach / pasują do określonych wzorców globalnych. Nigdy więcej nie będziesz musiał myśleć o własnym ładowaniu skryptu, gdy będziesz mieć te ostatnie opcje.

Konkluzja?

Wymagaj to świetne narzędzie do niektórych rzeczy. Ale idź z ziarnem, gdy tylko jest to możliwe, i oddzielaj swoje obawy, gdy tylko jest to możliwe. Niech Angular martwi się o własny wzorzec modularyzacji Angulara i rozważ użycie modułów ES6 lub CommonJS jako ogólnego wzorca modularyzacji. Niech nowoczesne narzędzia automatyzacji martwią się ładowaniem skryptów i zarządzaniem zależnościami. I zajmuj się asynchronicznym leniwym ładowaniem w bardziej szczegółowy sposób, zamiast mieszać go z pozostałymi dwoma problemami.

To powiedziawszy, jeśli tworzysz aplikacje Angular, ale z jakiegoś powodu nie możesz zainstalować Node na swoim komputerze, aby korzystać z narzędzi automatyzacji Javascript, to Require może być dobrym alternatywnym rozwiązaniem. I widziałem naprawdę skomplikowane konfiguracje, w których ludzie chcą dynamicznie ładować komponenty Angular, które deklarują swoje zależności lub coś w tym rodzaju. I chociaż prawdopodobnie spróbowałbym rozwiązać ten problem w inny sposób, widzę zalety tego pomysłu w tej bardzo szczególnej sytuacji.

Ale poza tym ... zaczynając od zera dzięki nowej aplikacji Angular i elastyczności, aby stworzyć nowoczesne środowisko automatyzacji ... masz wiele innych, bardziej elastycznych, bardziej nowoczesnych opcji.

(Aktualizowane wielokrotnie, aby nadążać za rozwijającą się sceną JS).

XML
źródło
1
Projekt zarodkowy NG- Boilerplate ( github.com/ngbp/ngbp ) tworzy również stronę internetową z jedną stroną z jednym plikiem js. Użycie manifestu HTML5 zapewnia, że ​​ten plik jest ładowany tylko raz dla każdej wersji.
Federico Elles
2
Chociaż, jak zawsze, <i> to zależy </i>. Wiele osób korzysta z Require w całej swojej architekturze i musi zintegrować Angular z tym ekosystemem. To zupełnie inna sytuacja niż w przypadku budowania aplikacji w izolacji.
Dave Nichol
2
Zgoda. Ale celem PO wydaje się być: „Jeśli buduję aplikację głównie w Angularu i (domyślnie) robię to w erze Grunta, i być może mam kilka dodatkowych zależności bibliotecznych, czy wymaga dodania wyraźnej, konkretnej wartości poza co otrzymam, używając Angulara bez wymagań? ” I wierzę, że odpowiedź brzmi: nie. Jeśli masz ogromną aplikację z 40 zewnętrznymi zależnościami lub nie możesz kontrolować swojego środowiska CI, lub twój szef uwielbia Wymagaj, lub uwielbiasz Wymagaj, albo Angular jest tylko jednym z elementów większej aplikacji itp. Itd., To YMMV.
XML
1
Ale ponieważ wydaje się, że nie zadaje tych pytań, a ponieważ po prostu wspomina o alternatywnym kontekście aplikacji Backbone, wydaje się pytać: „czy waniliowy Angular potrzebuje efektywnego zarządzania jego elementami?” A odpowiedź brzmi: „nie, chyba że dzieje się coś innego”. To pytanie pojawiło się także u progu ruchu JavaScript CI, w którym mamy znacznie lepsze sposoby radzenia sobie z podstawowym, fizycznym „ładowaniem skryptów”. Jeśli masz ten problem rozwiązany, Wymagaj polega zasadniczo na dopasowywaniu zależności i enkapsulacji. Angular robi obie te rzeczy dla ciebie.
XML
Google używa leniwego ładowania w niektórych swoich projektach AngularJS, ponieważ w przeciwnym razie użytkownik pobierałby 24 MB plików przy ładowaniu pierwszej strony (i to z plikami nieglikowanymi i łączonymi). Tak więc, w złożonych aplikacjach nie wystarczy po prostu połączyć wszystkie sekcje, gdy są sekcje, użytkownik nie będzie się otwierać przy każdej wizycie.
ngDeveloper
136

Tak, to ma sens.

Moduły kątowe nie próbują rozwiązać problemu porządkowania obciążenia skryptu lub opóźnionego pobierania skryptu. Cele te są ortogonalne i oba systemy modułów mogą żyć obok siebie i spełniać swoje cele.

Źródło: oficjalna strona Angular JS

Tiago Reis
źródło
6
Jeśli używasz jednego modułu na plik js, możesz załadować moduł kątowy w dowolnej kolejności. Ale jeśli chcesz na przykład umieścić różne usługi w różnych plikach js, ale chcesz dołączyć je do tego samego modułu kątowego, musisz załadować deklarację modułu przed deklaracją usług. To jest decyzja architektoniczna.
Matohawk
@Tiago: Podaj link do lokalizacji, z której pochodzi. Nigdzie nie mogę tego znaleźć. Zgaduję, że pochodzi on z wcześniejszej wersji dokumentacji Angulara, zanim wzorce Angulara stały się równie dobrze ustalone, i zanim stało się jasne, że unikanie Wymagania ma znaczące zalety, przynajmniej w przypadku komponentów Angulara.
XML
@XMLilley: czy możesz podać link wyjaśniający zalety unikania Wymagaj podczas korzystania z Angulara? Podejmuję decyzję, czy w moim projekcie użyć opcji Wymagaj, a to wydaje się pomocne.
Trevor
1
W moim języku byłam niejasna: korzyści płynące z korzystania z wbudowanych modułów ładujących Angulara i wykorzystywania wzorców Angulara są znaczne. Pytanie nie dotyczy tego, czy należy unikać Wymagaj, ale raczej, czy dodanie dodatkowej warstwy złożoności ma wartość. Oczywiste jest, że wbudowane wzorce Angulara w wygodny i elegancki sposób zaspokoją potrzebę ładowania własnych modułów Angulara. Jeśli Require służy do ładowania modułów poza kontekstem Angular, niech tak będzie. Ale użycie Require for Angular jest obce.
XML
6
@XMLilley wszystko, co robi Angular, daje zastrzyk zależności. Rzeczywiste ładowanie modułu jest Twoją odpowiedzialnością. Możesz to zrobić, dodając tag skryptu, posiadając skrypt kompilacji lub korzystając z wymagań. System modułowy Angulars nie ma na ten temat zdania.
gillesruppert
57

Uważam to za subiektywne pytanie, dlatego przedstawię swoją subiektywną opinię.

Angular ma wbudowany mechanizm modularyzacji. Gdy tworzysz aplikację, pierwszą rzeczą, którą powinieneś zrobić

var app = angular.module("myApp");

i wtedy

app.directive(...);

app.controller(...);

app.service(...);

Jeśli spojrzysz na ziarno kątowe, które jest zgrabną aplikacją startową dla kątownika, rozdzieliły one dyrektywy, usługi, kontrolery itp. Na różne moduły, a następnie załadowały te moduły jako zależności w głównej aplikacji.

Coś jak :

var app = angular.module("myApp",["Directives","Controllers","Services"];

Angular również leniwie ładuje te moduły (do pamięci), a nie ich pliki skryptów.

Jeśli chodzi o leniwe ładowanie plików skryptów, szczerze mówiąc, chyba że piszesz coś bardzo dużego, byłoby to przesadą, ponieważ kątowe z samej swojej natury zmniejsza ilość pisanego kodu. Typowa aplikacja napisana w większości innych frameworków mogłaby oczekiwać zmniejszenia LOC o około 30-50%, jeśli jest napisana pod kątem.

ganaraj
źródło
5
Rzeczywiście lepiej skonfigurować usługi w Angular.js niż ładować moduły za pomocą Require.js. Ułatwia to grę z $ $ i usługami, tak jak grałem z Socket.io
Marco Godínez
33

Używanie RequireJS z AngularJS ma sens, ale tylko wtedy, gdy zrozumiesz, jak każdy z nich działa w odniesieniu do wstrzykiwania zależności , ponieważ chociaż oba wstrzykują zależności, wstrzykują bardzo różne rzeczy.

AngularJS ma własny system zależności, który pozwala wstrzykiwać moduły AngularJS do nowo utworzonego modułu w celu ponownego wykorzystania implementacji. Załóżmy, że utworzyłeś „pierwszy” moduł, który implementuje filtr „pozdrawiam” AngularJS:

angular
  .module('first', [])
  .filter('greet', function() {
    return function(name) {
      return 'Hello, ' + name + '!';
    }
  });

A teraz załóżmy, że chcesz użyć filtru „pozdrawiam” w innym module o nazwie „drugi”, który implementuje filtr „do widzenia”. Możesz to zrobić, wstrzykując moduł „pierwszy” do modułu „drugi”:

angular
  .module('second', ['first'])
  .filter('goodbye', function() {
    return function(name) {
      return 'Good bye, ' + name + '!';
    }
  });

Chodzi o to, że aby działało poprawnie bez RequireJS, musisz upewnić się, że „pierwszy” moduł AngularJS jest załadowany na stronie przed utworzeniem „drugiego” modułu AngularJS. Cytowanie dokumentacji:

W zależności od modułu oznacza to, że wymagany moduł musi zostać załadowany przed załadowaniem wymaganego modułu.

W tym sensie RequireJS może ci pomóc, ponieważ RequireJS zapewnia czysty sposób na wstrzykiwanie skryptów na stronę, pomagając w organizacji zależności między nimi.

Wracając do „pierwszego” i „drugiego” modułu AngularJS, oto jak możesz to zrobić za pomocą RequireJS oddzielającego moduły w różnych plikach, aby wykorzystać ładowanie zależności skryptu:

// firstModule.js file
define(['angular'], function(angular) {
  angular
    .module('first', [])
    .filter('greet', function() {
      return function(name) {
        return 'Hello, ' + name + '!';
      }
    });
});
// secondModule.js file
define(['angular', 'firstModule'], function(angular) {
  angular
    .module('second', ['first'])
    .filter('goodbye', function() {
      return function(name) {
        return 'Good bye, ' + name + '!';
      }
    });
});

Widać, że jesteśmy zależni od pliku „firstModule”, który zostanie wstrzyknięty, zanim będzie można wykonać treść wywołania zwrotnego RequireJS, który wymaga załadowania „pierwszego” modułu AngularJS do utworzenia „drugiego” modułu AngularJS.

Uwaga dodatkowa: Wstrzykiwanie „kątowego” do plików „firstModule” i „secondModule”, ponieważ zależność jest wymagana, aby używać AngularJS wewnątrz funkcji wywołania zwrotnego RequireJS i należy go skonfigurować w konfiguracji RequireJS, aby odwzorować „angular” na kod biblioteki. Możliwe, że AngularJS również został załadowany na stronę w tradycyjny sposób (tag skryptu), chociaż pokonuje zalety RequireJS.

Więcej szczegółów na temat obsługi RequireJS z AngularJS od wersji 2.0 na moim blogu.

Na podstawie mojego postu na blogu „Sensing of RequireJS with AngularJS” , oto link .

leog
źródło
2
W rzeczywistości najlepiej, gdy dołączasz link, aby podsumować jego zawartość tutaj w Stack Overflow. Gdyby twój link kiedykolwiek się zepsuł, co robią w Internecie, twoja odpowiedź tutaj byłaby bezużyteczna dla przyszłych gości. Rozważ edycję, aby wprowadzić podsumowanie i ulepszyć ten post. Powodzenia!
jmort253
3
Proszę bardzo, dzięki jmort253.
leog
Dziękujemy za dokonanie tych edycji i wyjaśnienie, w jaki sposób RequireJS może pomóc w zarządzaniu zależnościami, aby uniknąć problemów z Angularem próbującym załadować coś, co jeszcze nie istnieje.
jmort253
całkowicie się zgadzam, najlepiej jest stosować to podejście w przypadku dużych aplikacji, jeśli nie, będziesz mieć wiele znaczników <script> w swojej aplikacji.
I.Tyger
21

Jak wspomniał @ganaraj, AngularJS ma zastrzyk zależności w swoim rdzeniu. Kiedy budowałem aplikacje z ziarnami zabawek z RequireJS i bez niego, osobiście odkryłem, że RequireJS był prawdopodobnie przesadny w większości przypadków użycia.

To nie znaczy, że RequireJS nie jest użyteczny ze względu na możliwości ładowania skryptów i utrzymywania bazy kodu w czystości podczas programowania. Połączenie optymalizatora r.js ( https://github.com/jrburke/r.js ) z migdałami ( https://github.com/jrburke/almond ) może stworzyć bardzo wąską historię ładowania skryptów. Jednak ponieważ jego funkcje zarządzania zależnościami nie są tak ważne, ponieważ kątowanie stanowi rdzeń aplikacji, możesz również oceniać inne rozwiązania ładowania skryptów po stronie klienta (HeadJS, LABjs, ...), a nawet po stronie serwera (MVC4 Bundler, ...) do konkretnego zastosowania.

Johnrich
źródło
17

Tak, szczególnie w przypadku bardzo dużych SPA.

W niektórych przypadkach RequireJS jest koniecznością. Na przykład tworzę aplikacje PhoneGap przy użyciu AngularJS, który również korzysta z Google Map API. Bez programu ładującego AMD, takiego jak RequireJS, aplikacja po prostu zawiesiłaby się po uruchomieniu w trybie offline, ponieważ nie może pozyskiwać skryptów interfejsu API Map Google. Moduł ładujący AMD daje mi możliwość wyświetlenia użytkownikowi komunikatu o błędzie.

Jednak integracja między AngularJS i RequireJS jest nieco trudna. Stworzyłem angularAMD, aby ten proces był mniej bolesny:

http://marcoslin.github.io/angularAMD/

marcoseu
źródło
7

Tak, sensowne jest użycie wymagaJS z Angularem, spędziłem kilka dni na testowaniu kilku rozwiązań technicznych.

Zrobiłem Angular Seed z RequireJS po stronie serwera. Bardzo prosty. Używam notacji SHIM dla żadnego modułu AMD, a nie AMD, ponieważ myślę, że bardzo trudno jest poradzić sobie z dwoma różnymi systemami wstrzykiwania zależności.

Używam grunt i r.js do łączenia plików js na serwerze w zależności od pliku konfiguracyjnego (zależności) SHIM. Odsyłam więc tylko jeden plik js w mojej aplikacji.

Aby uzyskać więcej informacji, odwiedź mój github Angular Seed: https://github.com/matohawk/angular-seed-requirejs

Matohawk
źródło
3

Unikałbym używania Require.js. Aplikacje, które widziałem, które to robią, kończą się bałaganem wielu rodzajów architektury wzorców modułów. AMD, Revealing, różne wersje IIFE itp. Istnieją inne sposoby ładowania na żądanie, takie jak mod Angular loadOnDemand . Dodanie innych rzeczy po prostu wypełnia twój kod pełen cruft i tworzy niski stosunek sygnału do szumu i sprawia, że ​​kod jest trudny do odczytania.

Julia Anne Jacobs
źródło
0

Myślę, że zależy to od złożoności projektu, ponieważ kątowość jest właściwie zmodularyzowana. Twoje kontrolery można zmapować i możesz po prostu zaimportować te klasy JavaScript na stronie index.html.

Ale na wypadek gdyby Twój projekt stał się większy. Lub przewidujesz taki scenariusz, powinieneś zintegrować grę kątową z wymaganiami. W tym artykule możesz zobaczyć aplikację demonstracyjną do takiej integracji.

Lastboy
źródło