2012-06-11 10 views
37

Uwielbiamy RequireJS i AMD w fazie rozwoju, gdzie możemy edytować moduł, przeładować w naszej przeglądarce i od razu zobaczyć wynik. Ale kiedy przychodzi czas, aby połączyć nasze moduły w jeden plik do wdrożenia produkcyjnego, najwyraźniej musi być obecny program ładujący AMD, niezależnie od tego, czy jest to sam RequireJS, czy też jego mniejszy partner "migdałowy", jak wyjaśniono tutaj:Dlaczego połączone moduły RequireJS AMD wymagają modułu ładującego?

http://requirejs.org/docs/faq-optimization.html#wrap

Moje zamieszanie jest następujące: dlaczego ładowarka jest w ogóle potrzebna? O ile nie wystąpią bardzo nietypowe okoliczności, które wymagają wykonania połączeń require() wewnątrz modułów, wydaje się, że seria modułów AMD może zostać połączona bez obecności ładowarki. Najprostszym możliwym przykładem będzie para modułów takich jak poniższe.

ModA.js:

define([], function() { 
    return {a: 1}; 
}); 

ModB.js:

define(['ModA'], function(A) { 
    return {b : 2}; 
}); 

Biorąc pod uwagę te dwa moduły, wydaje się, że może po prostu produkować concatenator poniższy tekst, a nie obciążać serwera produkcyjnego lub przeglądarka z dodatkową przepustowością lub obliczeniami wymaganymi przez RequireJS lub Almond.

sobie wyobrazić concatenator która produkuje (i używam szewron cudzysłowy «» aby pokazać, gdzie fragmenty z dwóch modułów powyżej zostały wstawione):

To tak daleko, jak tylko mogę patrz, poprawnie odtworzyć semantykę AMD, z minimalnym obcym klejem JavaScript. Czy jest dostępny taki konkatenator? Jeśli nie, czy byłbym głupcem, myśląc, że powinienem napisać jeden - czy naprawdę istnieje bardzo niewiele baz kodu, które składają się z prostych i czystych modułów napisanych przy pomocy define() i które nigdy nie potrzebują dalszych wywołań require() wewnątrz tego uruchomienia późniejszych asynchronicznych pobrań kodu?

+1

Jak rozwiązałeś ten problem? Zauważyłem, że przy użyciu migdałów, plik min jest większy o 3k niż połączony plik (9K vs 6K). – Naor

Odpowiedz

14

Optymalizator AMD ma możliwość optymalizacji większej liczby plików do pobrania, może także zoptymalizować liczbę modułów załadowanych do pamięci.

Na przykład, jeśli masz 10 modułów i możesz zoptymalizować je do 1 pliku, zapisałeś sobie 9 pobrań.

Jeśli Page1 używa wszystkich 10 modułów, to świetnie. Ale co jeśli strona2 używa tylko 1? Program ładujący AMD może opóźnić wykonanie "funkcji fabrycznej", dopóki moduł nie będzie miał wartości require "d. Dlatego Strona 2 uruchamia tylko jedną "funkcję fabryczną" do wykonania.

Jeśli każdy moduł zużyje 100 kb pamięci po tym, jak jest require 'd, struktura AMD, która ma optymalizację środowiska wykonawczego, zaoszczędzi również 900kb pamięci na stronie2.

Przykładem może być okno dialogowe "O boxie". Tam, gdzie sama realizacja jest opóźniona do ostatniej sekundy, ponieważ nie będzie dostępna w 99% przypadków. Na przykład. (W luźnym składni jQuery):

aboutBoxBtn.click(function() { 
    require(['aboutBox'], function (aboutBox) { 
     aboutBox.show(); 
    } 
}); 

zapisać koszt tworzenia obiektów JS i DOM powiązanej z „O Box”, dopóki nie jesteś pewien, że to konieczne.

Aby uzyskać więcej informacji, zobacz artykuł Delay executing defines until first require, aby dowiedzieć się, jak to zrobić.

+1

Interesujące! Tak więc, jeśli rozumiem, co mówisz, zakładasz kod, który tworzy obiekty i modyfikuje DOM * jedynie jako efekt uboczny bycia wymaganym *, czy to prawda? Nie pomyślałbym o tym, a jeśli ta praktyka jest powszechna, to prawdopodobnie trafilibyście na powody, dla których programiści JS lubią mieć ładowacz AMD w produkcji. Prawdopodobnie ze względu na moje tło w Pythonie, żaden z moich kodów nigdy nie jest wykonywany podczas importu - po prostu zwraca obiekt pełen funkcji, aby zadzwonić, gdy ich efekty uboczne są w końcu potrzebne. –

+0

Twój przykład użycia pamięci jest często mylony z obciążeniem we/wy - w przypadku czegoś podobnego o pudełku wydaje się, że wcześniej można wczytać wygraną, ale wstrzymać inicjalizację, aby można było zaoszczędzić pamięć i konfigurację bez dużego, interaktywnego opóźnienia. –

+0

@Chris, Zgadzam się z twoimi punktami, ale chciałem tylko przedstawić przypadek posiadania programu ładującego AMD w czasie wykonywania. Mogę się martwić o zbyt wiele kodu wykonanego przy starcie, podczas gdy możesz się martwić opóźnieniami. Pomijając trywialne przypadki, nie sądzę, że w przypadku wydajności jest jeden uniwersalny. I w moim przykładzie nie byłoby opóźnienia, ponieważ wszystkie JS zostały załadowane, po prostu nie "wykonane". –

1

Jedyną realną korzyścią jest to, że korzystasz z modułów w różnych sekcjach, więc niezależnie jest buforowanie modułów.

0

Jeśli skompilujesz kod z require.js do jednego dużego pliku do produkcji, możesz użyć almond.js, aby całkowicie zastąpić żądanie.

Almond obsługuje tylko zarządzanie odniesieniami do modułów, a nie samo ładowanie, które nie jest już potrzebne.

Bądź ostrożny z restrictions migdałowy nakłada się w celu podjęcia pracy

0

Nie ma powodu, dlaczego nie nie mógłby być narzędziem budowania takiego jak ten, który zaproponuje.

Ostatni raz * Sprawdziłem dane wyjściowe optymalizatora, przekonwertowałem moduły na wyraźnie nazwane moduły, a następnie zsumowałem je. Polegał na tym, aby upewnić się, że funkcje fabryczne zostały wywołane we właściwej kolejności, a właściwe obiekty modułu zostały przekazane. Aby zbudować narzędzie, które chcesz, musisz jawnie linearyzować moduły - nie niemożliwe, ale o wiele więcej pracy. Pewnie dlatego nie zostało to zrobione.

Wierzę **, że optymalizator ma funkcję automatycznego włączania wymagającego (lub migdałowego) do zbudowanego pliku, więc musisz mieć tylko jedno pobranie. Byłoby to większe niż wyjście narzędzia budowy, które chcesz, ale poza tym samo.

Jeśli istniało narzędzie do kompilacji, które produkowało żądany wynik, to musiałoby być bardziej ostrożne, w przypadku synchronicznego require, użycie exports zamiast powrotu i jakiejkolwiek innej kompatybilności z CommonJS cechy.

* To było kilka lat temu. 2010, myślę.

** Ale nie może tego teraz znaleźć.

1

Miałem taką samą potrzebę, więc stworzyłem prosty "kompilator" AMD do tego celu, który właśnie to robi. Możesz go uzyskać pod adresem https://github.com/amitayh/amd-compiler

Należy pamiętać, że brakuje wielu funkcji, ale wykona to zadanie (przynajmniej dla mnie). Zapraszam do udziału w Kodzie.

Powiązane problemy