Jest tak wiele różnych sposobów na włączenie JavaScript na stronie HTML. Wiem o następujących opcjach:
- kod wewnętrzny lub ładowany z zewnętrznego identyfikatora URI
- zawarte w znaczniku <head> lub <body> [ 1 , 2 ]
- brak
defer
lubasync
atrybut (tylko zewnętrzne skrypty) - zawarty w źródle statycznym lub dodawany dynamicznie przez inne skrypty (w różnych stanach analizy, przy użyciu różnych metod)
Nie licząc skryptów przeglądarki z dysku twardego, javascript: URI i onEvent
-attributes [ 3 ], istnieje już 16 alternatyw dla wykonania JS i jestem pewien, że coś zapomniałem.
Nie interesuje mnie szybkie (równoległe) ładowanie, bardziej jestem ciekawy kolejności wykonywania (która może zależeć od kolejności ładowania i kolejności dokumentów ). Czy istnieje dobre odniesienie (dla różnych przeglądarek), które obejmuje naprawdę wszystkie przypadki? Np. Http://www.websiteoptimization.com/speed/tweak/defer/ zajmuje się tylko 6 z nich i testuje głównie stare przeglądarki.
Ponieważ obawiam się, że nie ma, oto moje konkretne pytanie: Mam kilka (zewnętrznych) skryptów głównych do inicjalizacji i ładowania skryptów. Potem mam dwa statyczne, wbudowane skrypty na końcu ciała. Pierwszy pozwala modułowi ładującemu skrypt dynamicznie dołączać kolejny element skryptu (odwołując się do zewnętrznego js) do ciała. Drugi ze statycznych, wbudowanych skryptów chce użyć js z dodanego zewnętrznego skryptu. Czy może polegać na tym, że drugi został wykonany (i dlaczego :-)?
źródło
Odpowiedzi:
Jeśli nie ładujesz dynamicznie skryptów ani nie zaznaczasz ich jako
defer
lubasync
, wówczas skrypty są ładowane w kolejności podanej na stronie. Nie ma znaczenia, czy jest to skrypt zewnętrzny czy skrypt wbudowany - są one wykonywane w kolejności, w jakiej występują na stronie. Skrypty wbudowane, które pojawiają się po skryptach zewnętrznych, są wstrzymywane do momentu załadowania i uruchomienia wszystkich skryptów zewnętrznych poprzedzających je.Skrypty asynchroniczne (niezależnie od tego, jak są określone jako asynchroniczne) ładują się i działają w nieprzewidywalnej kolejności. Przeglądarka ładuje je równolegle i można je uruchamiać w dowolnej kolejności.
Nie ma przewidywalnego porządku wśród wielu rzeczy asynchronicznych. Gdyby ktoś potrzebował przewidywalnego porządku, musiałby zostać zakodowany poprzez rejestrację powiadomień o ładowaniu ze skryptów asynchronicznych i ręczne sekwencjonowanie wywołań javascript, gdy odpowiednie rzeczy zostaną załadowane.
Gdy znacznik skryptu jest wstawiany dynamicznie, sposób zachowania kolejności wykonywania zależeć będzie od przeglądarki. W tym artykule referencyjnym możesz zobaczyć, jak zachowuje się Firefox . Krótko mówiąc, nowsze wersje Firefoksa domyślnie domyślnie dodają dynamicznie znacznik skryptu do asynchronizacji, chyba że znacznik skryptu został ustawiony inaczej.
Tag skryptu z
async
można uruchomić natychmiast po załadowaniu. W rzeczywistości przeglądarka może zatrzymać analizator składni od wszystkiego, co robił i uruchomić ten skrypt. Tak naprawdę może działać prawie w dowolnym momencie. Jeśli skrypt został buforowany, może zostać uruchomiony niemal natychmiast. Jeśli skrypt ładuje się chwilę, może działać po zakończeniu parsera. Jedyną rzeczą, o której należy pamiętać,async
jest to, że może ona działać w dowolnym momencie i że czas ten nie jest przewidywalny.Tag skryptu z
defer
oczekiwaniem na zakończenie całego parsera, a następnie uruchamia wszystkie skrypty oznaczonedefer
w kolejności ich napotkania. Umożliwia to oznaczenie kilku skryptów, które zależą od siebie jakodefer
. Wszystkie zostaną odłożone na później, aż do zakończenia parsera dokumentów, ale wykonają je w kolejności, w jakiej napotkano, zachowując swoje zależności. Myślę, żedefer
skrypty są upuszczane w kolejce, która zostanie przetworzona po zakończeniu parsera. Technicznie rzecz biorąc, przeglądarka może pobierać skrypty w tle w dowolnym momencie, ale nie wykonają ani nie zablokują parsera, dopóki parser nie zakończy parsowania strony oraz parsowania i uruchamiania wszelkich wbudowanych skryptów, które nie są oznaczonedefer
lubasync
.Oto cytat z tego artykułu:
Odpowiednia część specyfikacji HTML5 (dla nowszych zgodnych przeglądarek) znajduje się tutaj . Wiele się tam pisze o zachowaniu asynchronicznym. Oczywiście ta specyfikacja nie dotyczy starszych przeglądarek (lub źle dostosowanych przeglądarek), których zachowanie prawdopodobnie musiałbyś przetestować w celu ustalenia.
Cytat ze specyfikacji HTML5:
Co ze skryptami modułów JavaScript
type="module"
?JavaScript obsługuje teraz ładowanie modułów o takiej składni:
Lub z
src
atrybutem:Wszystkie skrypty z
type="module"
automatycznie otrzymujądefer
atrybut. Spowoduje to pobranie ich równolegle (jeśli nie w linii) z innym ładowaniem strony, a następnie uruchomi je w kolejności, ale po zakończeniu parsera.Skrypty modułowe mogą również otrzymać
async
atrybut, który będzie uruchamiał wbudowane skrypty modułowe tak szybko, jak to możliwe, nie czekając na zakończenie parsera i nie czekając na uruchomienieasync
skryptu w określonej kolejności w stosunku do innych skryptów.Istnieje całkiem przydatny wykres na osi czasu, który pokazuje pobieranie i wykonywanie różnych kombinacji skryptów, w tym skryptów modułowych w tym artykule: Ładowanie modułu JavaScript .
źródło
defer
daje parserowi możliwość rozpoczęcia pobierania wcześniej, jednocześnie odraczając jego wykonanie. Pamiętaj, że jeśli masz wiele skryptów z tego samego hosta, to rozpoczęcie pobierania wcześniej może faktycznie spowolnić pobieranie innych z tego samego hosta (ponieważ rywalizują o przepustowość), na który czeka Twoja strona (które nie sądefer
), więc może to być obosieczny miecz.Przeglądarka wykona skrypty w kolejności, w jakiej je znajdzie. Wywołanie zewnętrznego skryptu spowoduje zablokowanie strony, dopóki skrypt nie zostanie załadowany i wykonany.
Aby przetestować ten fakt:
Dynamicznie dodawane skrypty są wykonywane, gdy tylko zostaną dołączone do dokumentu.
Aby przetestować ten fakt:
Kolejność alertów to „dołączone” -> „cześć!” -> „ostateczny”
Jeśli w skrypcie próbujesz uzyskać dostęp do elementu, który nie został jeszcze osiągnięty (przykład
<script>do something with #blah</script><div id="blah"></div>
:), pojawi się błąd.Ogólnie rzecz biorąc, tak, możesz dołączyć zewnętrzne skrypty, a następnie uzyskać dostęp do ich funkcji i zmiennych, ale tylko wtedy, gdy wyjdziesz z bieżącego
<script>
znacznika i uruchomisz nowy.źródło
Świetne podsumowanie autorstwa @addyosmani
Bezwstydnie skopiowane z https://addyosmani.com/blog/script-priorities/
źródło
Po przetestowaniu wielu opcji odkryłem, że następujące proste rozwiązanie polega na ładowaniu dynamicznie ładowanych skryptów w kolejności, w jakiej są one dodawane we wszystkich nowoczesnych przeglądarkach
źródło