Używam kilku wtyczek, niestandardowych widżetów i kilku innych bibliotek JQuery. w rezultacie mam kilka plików .js i .css. Muszę utworzyć program ładujący dla mojej witryny, ponieważ ładowanie zajmuje trochę czasu. byłoby miło, gdybym mógł wyświetlić program ładujący przed zaimportowaniem wszystkich:
<script type="text/javascript" src="js/jquery-1.6.2.min.js"></script>
<script type="text/javascript" src="js/myFunctions.js"></script>
<link type="text/css" href="css/main.css" rel="stylesheet" />
...
....
etc
Znalazłem kilka samouczków, które umożliwiają mi asynchroniczne importowanie biblioteki JavaScript. na przykład mogę zrobić coś takiego:
(function () {
var s = document.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.src = 'js/jquery-ui-1.8.16.custom.min.js';
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
})();
z jakiegoś powodu, gdy robię to samo dla wszystkich moich plików, strony nie działają. Od tak dawna próbuję znaleźć przyczynę problemu, ale po prostu nie mogę go znaleźć. Najpierw pomyślałem, że to prawdopodobnie dlatego, że niektóre funkcje javascript zależą od innych. ale załadowałem je we właściwej kolejności, korzystając z funkcji limitu czasu, gdy jedna została zakończona, przeszedłem do następnej, a strona nadal zachowuje się dziwnie. na przykład nie mogę klikać linków itp ... animacje jednak nadal działają ..
Tak czy inaczej
Oto, o czym myślałem ... Uważam, że przeglądarki mają pamięć podręczną, dlatego ładowanie strony po raz pierwszy zajmuje dużo czasu, a następnym razem jest szybkie. więc myślę o zastąpieniu mojej strony index.html stroną, która ładuje wszystkie te pliki asynchronicznie. po zakończeniu ładowania AJAX wszystkie te pliki przekierowują do strony, której zamierzam użyć. podczas korzystania z tej strony ładowanie tej strony nie powinno zająć dużo czasu, ponieważ pliki powinny już znajdować się w pamięci podręcznej przeglądarki. na mojej stronie indeksu (strona, na której pliki .js i .css są ładowane asynchronicznie) nie obchodzą mnie błędy. Będę po prostu wyświetlać program ładujący i przekierowywać stronę po zakończeniu ...
Czy to dobra alternatywa? czy powinienem nadal próbować implementować metody asynchroniczne?
EDYTOWAĆ
sposób, w jaki ładuję wszystko asynchronicznie, wygląda następująco:
importScripts();
function importScripts()
{
//import: jquery-ui-1.8.16.custom.min.js
getContent("js/jquery-1.6.2.min.js",function (code) {
var s = document.createElement('script');
s.type = 'text/javascript';
//s.async = true;
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext1,1);
});
//import: jquery-ui-1.8.16.custom.min.js
function insertNext1()
{
getContent("js/jquery-ui-1.8.16.custom.min.js",function (code) {
var s = document.createElement('script');
s.type = 'text/javascript';
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext2,1);
});
}
//import: jquery-ui-1.8.16.custom.css
function insertNext2()
{
getContent("css/custom-theme/jquery-ui-1.8.16.custom.css",function (code) {
var s = document.createElement('link');
s.type = 'text/css';
s.rel ="stylesheet";
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext3,1);
});
}
//import: main.css
function insertNext3()
{
getContent("css/main.css",function (code) {
var s = document.createElement('link');
s.type = 'text/css';
s.rel ="stylesheet";
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext4,1);
});
}
//import: jquery.imgpreload.min.js
function insertNext4()
{
getContent("js/farinspace/jquery.imgpreload.min.js",function (code) {
var s = document.createElement('script');
s.type = 'text/javascript';
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext5,1);
});
}
//import: marquee.js
function insertNext5()
{
getContent("js/marquee.js",function (code) {
var s = document.createElement('script');
s.type = 'text/javascript';
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext6,1);
});
}
//import: marquee.css
function insertNext6()
{
getContent("css/marquee.css",function (code) {
var s = document.createElement('link');
s.type = 'text/css';
s.rel ="stylesheet";
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext,1);
});
}
function insertNext()
{
setTimeout(pageReadyMan,10);
}
}
// get the content of url and pass that content to specified function
function getContent( url, callBackFunction )
{
// attempt to create the XMLHttpRequest and make the request
try
{
var asyncRequest; // variable to hold XMLHttpRequest object
asyncRequest = new XMLHttpRequest(); // create request object
// register event handler
asyncRequest.onreadystatechange = function(){
stateChange(asyncRequest, callBackFunction);
}
asyncRequest.open( 'GET', url, true ); // prepare the request
asyncRequest.send( null ); // send the request
} // end try
catch ( exception )
{
alert( 'Request failed.' );
} // end catch
} // end function getContent
// call function whith content when ready
function stateChange(asyncRequest, callBackFunction)
{
if ( asyncRequest.readyState == 4 && asyncRequest.status == 200 )
{
callBackFunction(asyncRequest.responseText);
} // end if
} // end function stateChange
a najdziwniejsze jest to, że działa cały styl plus wszystkie funkcje javascript. strona jest jednak zawieszona z jakiegoś powodu ...
źródło
document.head.appendChild
, jednak są pewne niszowe problemy z dodawaniem skryptów do<head>
; nic, co uniemożliwiłoby ładowanie i wykonywanie skryptów.document.write
przed załadowaniem dokumentu, skrypt zostanie wykonany synchronicznie jako część ładowania strony i sam nie będzie zawierał żadnego asynchronicznego zachowania wywołania zwrotnego. Jeśli tworzysz element skryptu i dodajesz go do strony, będziesz mieć dostęp do dodawania detektorów zdarzeń, które będą wyzwalane asynchronicznie. tl; dr: to zależy od tego, jak ładujesz skrypt za pomocą JS.Nowy atrybut „async” HTML5 powinien załatwić sprawę. Większość przeglądarek obsługuje również „defer”, jeśli zależy Ci na IE.
async - plik HTML
defer - kod HTML
Analizując nowy kod jednostki reklamowej AdSense, zauważyłem, że atrybut i wyszukiwanie prowadzą mnie tutaj: http://davidwalsh.name/html5-async
źródło
async
lubdefer
zablokuje renderowanie podczas ładowania. Ustawienieasync
powie mu, aby nie blokował i nie uruchamiał skryptu jak najszybciej. Ustawieniedefer
powie mu, aby nie blokował, ale czekał z uruchomieniem skryptu, aż strona zostanie ukończona. Zwykle nie ma problemu z uruchamianiem skryptów jak najszybciej, o ile nie mają one żadnych zależności (np. JQuery). Jeśli jeden skrypt jest zależny od innego, użyj,onLoad
aby poczekać.Załadowałem skrypty asynchronicznie (HTML 5 ma tę funkcję) po zakończeniu ładowania wszystkich skryptów przekierowałem stronę do index2.html, gdzie index2.html używa tych samych bibliotek. Ponieważ przeglądarki mają pamięć podręczną, gdy strona przekierowuje do index2.html, index2.html ładuje się w mniej niż sekundę, ponieważ ma wszystko, czego potrzeba do załadowania strony. Na mojej stronie index.html ładuję również obrazy, których planuję użyć, aby przeglądarka umieściła te obrazy w pamięci podręcznej. więc mój index.html wygląda następująco:
Kolejną fajną rzeczą jest to, że mogę umieścić program ładujący na stronie, a po zakończeniu ładowania strony program ładujący zniknie i po kilku milisekundach nowa strona będzie uruchomiona.
źródło
Przykład z google
źródło
Kilka uwag:
s.async = true
nie jest zbyt poprawny dla dokumentu HTML5, poprawnys.async = 'async'
(w rzeczywistości użycietrue
jest poprawne , dzięki amn, który wskazał to w komentarzu poniżej)Ponieważ istnieje niedawny powód, aby ładować pliki asynchronicznie, ale w porządku, polecam nieco bardziej funkcjonalny sposób na twój przykład (usuń
console.log
do użytku produkcyjnego :)):źródło
s.async = true
jest poprawne . Właściwośćasync
jest wyraźnie określona jako wartość logiczna w zaleceniu W3C dotyczącym HTML 5 pod adresem w3.org/TR/html5/scripting-1.html#attr-script-async . Myliszasync
atrybut zasync
właściwością udostępnianą przez obiekty implementująceHTMLScriptElement
interfejs DOM. Rzeczywiście, manipulując odpowiednim atrybutem elementu za pomocą czegoś podobnegoElement.setAttribute
, powinieneś używać,element.setAttribute("async", "async")
ponieważ wszystkie atrybuty HTML są przede wszystkim tekstem.Dzięki HTML5 możesz teraz zadeklarować skrypty, które chcesz ładować asynchronicznie, dodając „async” w tagu:
Uwaga: Atrybut async jest przeznaczony tylko dla skryptów zewnętrznych (i powinien być używany tylko wtedy, gdy atrybut src jest obecny).
Uwaga: istnieje kilka sposobów wykonania zewnętrznego skryptu:
Zobacz: http://www.w3schools.com/tags/att_script_async.asp
źródło
Uzupełniłbym odpowiedź zzzzBov sprawdzeniem obecności callback i pozwoliłbym na przekazywanie argumentów:
źródło
Oto świetne, współczesne rozwiązanie asynchronicznego ładowania skryptów, chociaż dotyczy ono tylko skryptu js z async false .
Jest świetny artykuł napisany na www.html5rocks.com - Zanurz się głęboko w mętne wody ładowania skryptów .
Po rozważeniu wielu możliwych rozwiązań autor doszedł do wniosku, że dodanie skryptów js na końcu elementu body jest najlepszym sposobem na uniknięcie blokowania renderowania strony przez skrypty js.
W międzyczasie autor dodał kolejne dobre alternatywne rozwiązanie dla osób, które desperacko chcą ładować i wykonywać skrypty asynchronicznie.
Biorąc pod uwagę, że masz cztery nazwane skrypty
script1.js, script2.js, script3.js, script4.js
, możesz to zrobić, stosując async = false :Teraz Spec mówi : Pobierz razem, wykonuj po kolei, gdy tylko wszystko zostanie pobrane.
Firefox <3.6, Opera mówi: Nie mam pojęcia, co to jest „asynchronizacja”, ale tak się składa, że wykonuję skrypty dodane przez JS w kolejności, w jakiej są dodawane.
Safari 5.0 mówi: Rozumiem „async”, ale nie rozumiem ustawiania go na „false” w JS. Wykonam twoje skrypty, gdy tylko wylądują, w dowolnej kolejności.
IE <10 mówi: Nie mam pojęcia o „async”, ale można obejść ten problem przy użyciu „onreadystatechange”.
Wszystko inne mówi: jestem twoim przyjacielem, zrobimy to na podstawie książki.
Teraz pełny kod z obejściem IE <10:
źródło
Jednym z powodów, dla których skrypty ładują się tak wolno, jest to, że podczas ładowania strony uruchamiane były wszystkie skrypty, na przykład:
zamiast:
Ten drugi fragment skryptu czeka, aż przeglądarka całkowicie załaduje cały kod JavaScript, zanim rozpocznie wykonywanie któregokolwiek z twoich skryptów, dzięki czemu użytkownik będzie miał wrażenie, że strona załadowała się szybciej.
Jeśli chcesz poprawić wrażenia użytkownika poprzez skrócenie czasu ładowania, nie wybrałbym opcji „ekran ładowania”. Moim zdaniem byłoby to znacznie bardziej irytujące niż wolniejsze ładowanie strony.
źródło
Proponuję spojrzeć na Modernizr . Jest to mała, lekka biblioteka, którą możesz asynchronicznie ładować swój javascript z funkcjami, które pozwalają sprawdzić, czy plik jest załadowany i wykonać skrypt w innym określonym przez Ciebie.
Oto przykład ładowania jquery:
źródło
Napisałem mały post, aby w tym pomóc, możesz przeczytać więcej tutaj https://timber.io/snippets/asynchronously-load-a-script-in-the-browser-with-javascript/ , ale załączam klasa pomocnicza poniżej. Automatycznie zaczeka na załadowanie skryptu i zwróci określony atrybut okna, gdy to zrobi.
Użycie jest takie:
źródło
Ten artykuł na wiki może Cię zainteresować: http://ajaxpatterns.org/On-Demand_Javascript
Wyjaśnia, jak i kiedy stosować taką technikę.
źródło
Cóż,
x.parentNode
zwraca element HEAD, więc wstawiasz skrypt tuż przed tagiem head. Może to jest problem.Spróbuj
x.parentNode.appendChild()
zamiast tego.źródło
Sprawdź to https://github.com/stephen-lazarionok/async-resource-loader . Zawiera przykład, który pokazuje, jak załadować JS, CSS i wiele plików za jednym razem.
źródło
Możesz użyć LABJS lub RequreJS
Programy ładujące skrypty
LABJS
, takie jak ,RequireJS
poprawią szybkość i jakość kodu.źródło
Czy rozważałeś użycie funkcji Fetch Injection? Zainstalowałem bibliotekę open source o nazwie fetch-inject, aby obsługiwać takie przypadki. Oto jak może wyglądać program ładujący przy użyciu biblioteki lib:
Aby zapewnić kompatybilność wsteczną, skorzystaj z wykrywania funkcji i powróć do XHR Injection lub Script DOM Elements lub po prostu wstaw tagi do strony za pomocą
document.write
.źródło
Oto moje niestandardowe rozwiązanie eliminujące JavaScript blokujący renderowanie:
Krótko mówiąc, ładuje wszystkie skrypty asynchronicznie, a następnie wykonuje je w konsekwencji.
Repozytorium Github : https://github.com/mudroljub/js-async-loader
źródło
No 'Access-Control-Allow-Origin' header is present on the requested resource
Tutaj mała funkcja ES6, jeśli ktoś chce jej użyć na przykład w Reakcie
źródło
Proponuję najpierw zająć się minifikacją plików i sprawdzić, czy to daje wystarczająco duże zwiększenie prędkości. Jeśli Twój host działa wolno, możesz spróbować umieścić tę statyczną zawartość w sieci CDN.
źródło