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
<script src="loader.js"></script>
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
<script>useDebugVersion = true;</script>
<script src="loader.js"></script>
loader.js wygląda mniej więcej tak
if (useDebugVersion) {
injectScript("app.js");
injectScript("somelib.js");
injectScript("someotherlib.js");
injectScript("anotherlib.js");
... repeat for 60 files ...
} else {
injectScript("large-concatinated.js");
}
Skrypt budujący to po prostu plik .sh, który wygląda tak
cat > large-concantinated.js app.js somelib.js someotherlib.js anotherlib.js
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.js
Póź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
lub webpack
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
injectScript("lib1.js");
injectScript("lib2.js");
lib2 wymaga lib1. Zawiera kod, który robi coś podobnego
lib1Api.installPlugin(...);
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
require.config({
paths: {
lib1: './path/to/lib1',
lib2: './path/to/lib2',
},
shim: {
lib1: {
"exports": 'lib1Api',
},
lib2: {
"deps": ["lib1"],
},
}
});
Robimy to w naszym module korzystającym z lib1
define(['lib1'], function(lib1Api) {
lib1Api.doSomething(...);
});
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