Jaka jest różnica między użyciem Require.JS a zwykłym utworzeniem <script>
elementu w DOM?
Rozumiem, że Require.JS umożliwia ładowanie zależności, ale czy nie można tego zrobić po prostu poprzez utworzenie <script>
elementu, który ładuje niezbędny zewnętrzny plik JS?
Na przykład załóżmy, że mam funkcję doStuff()
, która wymaga tej funkcji needMe()
. doStuff()
znajduje się w pliku zewnętrznym do_stuff.js
, podczas gdy needMe()
znajduje się w pliku zewnętrznym need_me.js
.
Robiąc to w sposób Require.JS:
define(['need_me'],function(){
function doStuff(){
//do some stuff
needMe();
//do some more stuff
}
});
Robi się to po prostu tworząc element skryptu:
function doStuff(){
var scriptElement = document.createElement('script');
scriptElement.src = 'need_me.js';
scriptElement.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(scriptElement);
//do some stuff
needMe();
//do some more stuff
}
Obie te metody działają. Jednak druga wersja nie wymaga ode mnie załadowania całej biblioteki Require.js. Naprawdę nie widzę żadnej różnicy funkcjonalnej ...
javascript
requirejs
dynamic-script-loading
js-amd
maxedison
źródło
źródło
Odpowiedzi:
Oto fajny artykuł na ajaxian.com, dlaczego go używać:
RequireJS: asynchroniczne ładowanie JavaScript
źródło
W naszym przykładzie tag skryptu jest tworzony asynchronicznie, co oznacza, że
needMe()
funkcja zostanie wywołana przed zakończeniem ładowania pliku need_me.js. Powoduje to nieprzechwycone wyjątki, w których funkcja nie jest zdefiniowana.Zamiast tego, aby to, co sugerujesz, zadziałało, musisz zrobić coś takiego:
Prawdopodobnie najlepszym rozwiązaniem może być użycie menedżera pakietów, takiego jak RequireJS, lub wykorzystanie strategii opartej na czystym języku JavaScript, jak pokazano powyżej. Chociaż aplikacja sieci Web może ładować się szybciej, wywoływanie funkcji i funkcji w witrynie byłoby wolniejsze, ponieważ wymagałoby oczekiwania na załadowanie zasobów przed wykonaniem tej czynności.
Jeśli aplikacja internetowa jest zbudowana jako aplikacja jednostronicowa, weź pod uwagę, że ludzie nie będą często ponownie ładować strony. W takich przypadkach wstępne załadowanie wszystkiego pomoże sprawić, że doświadczenie będzie wydawać się szybsze podczas rzeczywistego korzystania z aplikacji. W takich przypadkach masz rację, możesz po prostu załadować wszystkie zasoby, po prostu umieszczając tagi skryptu w nagłówku lub treści strony.
Jednak w przypadku tworzenia witryny internetowej lub aplikacji sieci Web zgodnej z bardziej tradycyjnym modelem, w którym przechodzi się ze strony na stronę, powodując przeładowanie zasobów, podejście z opóźnionym ładowaniem może pomóc przyspieszyć te przejścia.
źródło
Kilka innych bardzo wskazanych powodów, dla których używanie RequireJS ma sens:
Zaczerpnięte z komentarzy rmurpheya w tym streszczeniu .
Warstwy abstrakcji mogą być koszmarem, którego trzeba się nauczyć i do którego można się przystosować, ale kiedy służy celowi i robi to dobrze, ma po prostu sens.
źródło
Oto bardziej konkretny przykład.
Pracuję w projekcie z 60 plikami. Mamy 2 różne tryby działania.
Załaduj połączoną wersję, 1 duży plik. (Produkcja)
Załaduj wszystkie 60 plików (programowanie)
Używamy programu ładującego, więc na stronie mamy tylko jeden skrypt
Domyślnie jest to tryb nr 1 (ładowanie jednego dużego połączonego pliku). Aby uruchomić tryb in # 2 (oddzielne pliki), ustawiliśmy flagę. To może być wszystko. Klucz w ciągu zapytania. W tym przykładzie po prostu to robimy
loader.js wygląda mniej więcej tak
Skrypt budujący to po prostu plik .sh, który wygląda tak
itp...
Jeśli zostanie dodany nowy plik, prawdopodobnie będziemy używać trybu nr 2, ponieważ pracujemy nad rozwojem, musimy dodać
injectScript("somenewfile.js")
linię do loader.jsPóźniej do produkcji musimy również dodać somenewfile.js do naszego skryptu kompilacji. Krok, o którym często zapominamy, a następnie otrzymujemy komunikaty o błędach.
Przechodząc na AMD nie musimy edytować 2 plików. Problem z utrzymaniem synchronizacji loader.js i skryptu kompilacji znika. Używając
r.js
lubwebpack
może po prostu odczytać kod do zbudowanialarge-concantinated.js
Potrafi również radzić sobie z zależnościami, na przykład mieliśmy 2 pliki lib1.js i lib2.js załadowane w ten sposób
lib2 wymaga lib1. Zawiera kod, który robi coś podobnego
Ale ponieważ wstrzyknięte skrypty są ładowane asynchronicznie, nie ma gwarancji, że zostaną załadowane we właściwej kolejności. Te 2 skrypty nie są skryptami AMD, ale używając require.js możemy określić ich zależności
Robimy to w naszym module korzystającym z lib1
Teraz require.js wstrzyknie skrypty za nas i nie wstrzyknie lib2, dopóki lib1 nie zostanie załadowana, ponieważ powiedzieliśmy, że lib2 zależy od lib1. Nie uruchomi również naszego modułu używającego lib1, dopóki nie załaduje się zarówno lib2, jak i lib1.
To sprawia, że programowanie jest przyjemne (bez etapu kompilacji, bez martwienia się o kolejność ładowania) i sprawia, że produkcja jest przyjemna (nie ma potrzeby aktualizowania skryptu kompilacji dla każdego dodanego skryptu).
Jako dodatkowy bonus możemy użyć wtyczki babel pakietu webpack, aby uruchomić babel na kodzie dla starszych przeglądarek i znowu nie musimy też utrzymywać tego skryptu budującego.
Zwróć uwagę, że gdyby Chrome (nasza wybrana przeglądarka) zaczął obsługiwać
import
naprawdę, prawdopodobnie przełączylibyśmy się na to w celu programowania, ale to tak naprawdę niczego nie zmieni. Moglibyśmy nadal używać webpacka do tworzenia połączonego pliku i moglibyśmy go użyć do uruchomienia babel na kodzie dla wszystkich przeglądarek.Wszystko to uzyskuje się nie używając tagów skryptów i używając AMD
źródło