Myślę, że Jake Archibald przedstawił nam pewne spostrzeżenia w 2013 roku, które mogą dodać jeszcze więcej pozytywności do tematu:
https://www.html5rocks.com/en/tutorials/speed/script-loading/
Święty Graal natychmiast pobiera zestaw skryptów, nie blokując renderowania, i wykonuje je jak najszybciej w kolejności, w jakiej zostały dodane. Niestety HTML cię nienawidzi i nie pozwala ci tego zrobić.
(...)
Odpowiedź znajduje się w specyfikacji HTML5, chociaż jest ukryta u dołu sekcji ładowania skryptów. „ Atrybut async IDL kontroluje, czy element będzie wykonywany asynchronicznie, czy nie. Jeśli ustawiona jest flaga„ force-async ”, to po uzyskaniu atrybutu async IDL musi zwrócić wartość true, a po ustawieniu„ force-async ” flaga musi być najpierw rozbrojona… ”.
(...)
Skrypty tworzone dynamicznie i dodawane do dokumentu są domyślnie asynchroniczne , nie blokują renderowania i nie są uruchamiane natychmiast po pobraniu, co oznacza, że mogą wyjść w niewłaściwej kolejności. Możemy jednak wyraźnie oznaczyć je jako niesynchroniczne:
[
'//other-domain.com/1.js',
'2.js'
].forEach(function(src) {
var script = document.createElement('script');
script.src = src;
script.async = false;
document.head.appendChild(script);
});
To daje naszym skryptom mieszankę zachowań, których nie da się osiągnąć za pomocą zwykłego HTML. Ponieważ jawnie nie są asynchroniczne, skrypty są dodawane do kolejki wykonawczej, tej samej kolejki, do której zostały dodane w naszym pierwszym przykładzie w formacie HTML. Ponieważ są tworzone dynamicznie, są wykonywane poza analizą dokumentów, więc renderowanie nie jest blokowane podczas pobierania (nie należy mylić ładowania niesynchronizowanego skryptu z synchronizacją XHR, co nigdy nie jest dobre).
Powyższy skrypt powinien zostać uwzględniony w nagłówku stron, kolejkując pobieranie skryptów tak szybko, jak to możliwe, bez zakłócania renderowania progresywnego, i wykonuje się tak szybko, jak to możliwe, w podanej kolejności. „2.js” można pobrać za darmo przed „1.js”, ale nie zostanie wykonane, dopóki „1.js” nie zostanie pomyślnie pobrane i wykonane lub nie wykona żadnego z nich. Hurra! pobieranie asynchroniczne, ale wykonanie zlecone !
Mimo to może to nie być najszybszy sposób ładowania skryptów:
(...) W powyższym przykładzie przeglądarka musi przeanalizować i wykonać skrypt, aby dowiedzieć się, które skrypty należy pobrać. To ukrywa twoje skrypty przed skanerami wstępnego ładowania. Przeglądarki używają tych skanerów do odkrywania zasobów na stronach, które prawdopodobnie będziesz odwiedzać dalej, lub odkrywania zasobów strony, gdy analizator jest zablokowany przez inny zasób.
Możemy ponownie dodać wykrywalność, umieszczając to w nagłówku dokumentu:
<link rel="subresource" href="//other-domain.com/1.js">
<link rel="subresource" href="2.js">
Mówi to przeglądarce, że strona potrzebuje wersji 1.js i 2.js. link [rel = subresource] jest podobny do link [rel = prefetch], ale ma inną semantykę. Niestety, obecnie jest obsługiwany tylko w Chrome i musisz zadeklarować, które skrypty załadować dwukrotnie, raz za pomocą elementów linku i ponownie w skrypcie.
Korekta: pierwotnie stwierdziłem, że zostały one pobrane przez skaner wstępnego ładowania, nie są, są one odbierane przez zwykły parser. Jednak skaner wstępnego ładowania może je pobrać, po prostu jeszcze tego nie robi, podczas gdy skrypty zawarte w kodzie wykonywalnym nigdy nie mogą zostać wstępnie załadowane. Dzięki Yoav Weiss, który poprawił mnie w komentarzach.
async
jest nowy (ish), aledefer
jest częścią IE od IE4.defer
został dodany do innych przeglądarek znacznie niedawno, ale starsze wersje tych przeglądarek mają tendencję do zawieszania się o wiele mniej.