Ich verwende mehrere Plugins, benutzerdefinierte Widgets und einige andere Bibliotheken von JQuery. Als Ergebnis habe ich mehrere .js- und .css-Dateien. Ich muss einen Loader für meine Site erstellen, da das Laden einige Zeit in Anspruch nimmt. Es ist schön, wenn ich den Loader anzeigen kann, bevor ich Folgendes importiere:
<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
Ich habe mehrere Tutorials gefunden, mit denen ich eine JavaScript-Bibliothek asynchron importieren kann. Zum Beispiel kann ich so etwas machen wie:
(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);
})();
Aus irgendeinem Grund funktionieren die Seiten nicht, wenn ich für alle meine Dateien dasselbe mache. Ich habe so lange versucht herauszufinden, wo das Problem liegt, aber ich kann es einfach nicht finden. Zuerst dachte ich, dass es wahrscheinlich daran lag, dass einige Javascript-Funktionen von den anderen abhingen. Aber ich habe sie in der richtigen Reihenfolge mit der Timeout-Funktion geladen, als eine abgeschlossen war. Ich fuhr mit der nächsten fort und die Seite verhält sich immer noch seltsam. Zum Beispiel kann ich nicht auf Links klicken usw. Animationen funktionieren trotzdem.
Sowieso
Hier ist, was ich gedacht habe ... Ich glaube, Browser haben einen Cache, deshalb dauert es lange, die Seite zum ersten Mal zu laden und das nächste Mal ist es schnell. Ich denke also daran, meine index.html-Seite durch eine Seite zu ersetzen, die alle diese Dateien asynchron lädt. Wenn Ajax fertig ist, leiten Sie alle Dateien weiter, die auf die Seite umgeleitet werden, die ich verwenden möchte. Wenn Sie diese Seite verwenden, sollte das Laden nicht lange dauern, da die Dateien bereits im Cache des Browsers enthalten sein sollten. Auf meiner Indexseite (Seite, auf der die Dateien .js und .css asynchron geladen werden) ist es mir egal, ob Fehler angezeigt werden. Ich werde nur einen Loader anzeigen und die Seite umleiten, wenn ich fertig bin ...
Ist diese Idee eine gute Alternative? oder sollte ich weiterhin versuchen, die asynchronen Methoden zu implementieren?
BEARBEITEN
Die Art und Weise, wie ich alles asynchron lade, ist wie folgt:
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
und der seltsame Teil ist, dass die gesamte Arbeit des Stils plus alle Javascript-Funktionen. Die Seite ist jedoch aus irgendeinem Grund eingefroren ...
quelle
document.head.appendChild
, es gibt jedoch einige Nischenprobleme beim Hinzufügen von Skripten zu<head>
; Nichts, was das Laden und Ausführen von Skripten verhindern würde.document.write
bevor das Dokument geladen wurde, wird das Skript beim Laden der Seite synchron ausgeführt und enthält kein eigenständiges asynchrones Rückrufverhalten. Wenn Sie ein Skriptelement erstellen und zur Seite hinzufügen, können Sie Ereignis-Listener hinzufügen, die asynchron ausgelöst werden. tl; dr: Es hängt davon ab, wie Sie das Skript mit JS laden.Das neue 'async'-Attribut von HTML5 soll den Trick machen. 'defer' wird auch in den meisten Browsern unterstützt, wenn Sie sich für IE interessieren.
async - Der HTML-Code
Aufschieben - Der HTML-Code
Bei der Analyse des neuen AdSense-Anzeigenblockcodes fiel mir das Attribut auf, und eine Suche führte mich hierher: http://davidwalsh.name/html5-async
quelle
async
oderdefer
blockiert es das Rendering, während es geladen wird. Durch die Einstellungasync
wird angewiesen, das Skript nicht so schnell wie möglich zu blockieren und auszuführen. Die Einstellungdefer
weist es an, nicht zu blockieren, sondern mit dem Ausführen des Skripts zu warten , bis die Seite fertig ist. Normalerweise ist es kein Problem, Skripte so schnell wie möglich auszuführen, solange sie keine Abhängigkeiten aufweisen (z. B. jQuery). Wenn ein Skript von einem anderen abhängig istonLoad
, warten Sie mit.Ich habe die Skripte asynchron geladen (HTML 5 hat diese Funktion), als alle Skripte geladen wurden. Ich habe die Seite nach index2.html umgeleitet, wobei index2.html dieselben Bibliotheken verwendet. Da Browser einen Cache haben, sobald die Seite zu index2.html umgeleitet wird, wird index2.html in weniger als einer Sekunde geladen, da alles vorhanden ist, was zum Laden der Seite erforderlich ist. Auf meiner index.html-Seite lade ich auch die Bilder, die ich verwenden möchte, damit der Browser diese Bilder in den Cache legt. meine index.html sieht also so aus:
Eine weitere nette Sache ist, dass ich möglicherweise einen Loader in die Seite einfügen kann. Wenn die Seite fertig geladen ist, verschwindet der Loader und in wenigen Millisekunden wird die neue Seite ausgeführt.
quelle
Beispiel von Google
quelle
Mehrere Anmerkungen:
s.async = true
ist nicht sehr korrekt für HTML5-Doctype, richtig ists.async = 'async'
(tatsächlich ist die Verwendungtrue
korrekt , dank amn, der im Kommentar unten darauf hingewiesen hat )Da es in letzter Zeit einen Grund gibt, Dateien asynchron zu laden, würde ich in der richtigen Reihenfolge eine etwas funktionalere Vorgehensweise gegenüber Ihrem Beispiel empfehlen (
console.log
für die Verwendung in der Produktion entfernen :)):quelle
s.async = true
ist richtig . Die Eigenschaftasync
wird in der HTML 5-Empfehlung von W3C unter w3.org/TR/html5/scripting-1.html#attr-script-async explizit als Boolescher Wert angegeben . Sie verwechseln dasasync
Attribut mit derasync
Eigenschaft, die von Objekten verfügbar gemacht wird, die dieHTMLScriptElement
DOM-Schnittstelle implementieren . In der Tat sollten Sie beim Bearbeiten des entsprechenden Attributs des Elements durch etwas wieElement.setAttribute
verwenden,element.setAttribute("async", "async")
da alle HTML-Attribute in erster Linie Text sind.Dank HTML5 können Sie jetzt die Skripte deklarieren, die Sie asynchron laden möchten, indem Sie dem Tag "async" hinzufügen:
Hinweis: Das asynchrone Attribut gilt nur für externe Skripte (und sollte nur verwendet werden, wenn das src-Attribut vorhanden ist).
Hinweis: Es gibt verschiedene Möglichkeiten, wie ein externes Skript ausgeführt werden kann:
Siehe dies: http://www.w3schools.com/tags/att_script_async.asp
quelle
Ich würde die Antwort von zzzzBov mit einer Überprüfung auf das Vorhandensein eines Rückrufs vervollständigen und die Übergabe von Argumenten zulassen:
quelle
Hier ist eine großartige zeitgemäße Lösung für das Laden von asynchronen Skripten, obwohl das js-Skript nur mit async false behandelt wird .
Es gibt einen großartigen Artikel in www.html5rocks.com - Tauchen Sie tief in das trübe Wasser des Ladens von Skripten ein .
Nach Prüfung vieler möglicher Lösungen kam der Autor zu dem Schluss, dass das Hinzufügen von JS-Skripten am Ende des Body-Elements der beste Weg ist, um das Blockieren des Seiten-Renderings durch JS-Skripte zu vermeiden.
In der Zwischenzeit fügte der Autor eine weitere gute alternative Lösung für diejenigen Personen hinzu, die unbedingt Skripte asynchron laden und ausführen möchten.
Wenn Sie vier Skripte mit dem Namen haben
script1.js, script2.js, script3.js, script4.js
, können Sie async = false anwenden :Jetzt sagt Spec : Gemeinsam herunterladen, in der richtigen Reihenfolge ausführen, sobald alle heruntergeladen sind.
Firefox <3.6, Opera sagt: Ich habe keine Ahnung, was dieses "asynchrone" Ding ist, aber es passiert einfach so, dass ich über JS hinzugefügte Skripte in der Reihenfolge ausführe, in der sie hinzugefügt wurden.
Safari 5.0 sagt: Ich verstehe "async", verstehe es aber nicht, es mit JS auf "false" zu setzen. Ich werde Ihre Skripte ausführen, sobald sie landen, in welcher Reihenfolge auch immer.
IE <10 sagt: Keine Ahnung von "async", aber es gibt eine Problemumgehung mit "onreadystatechange".
Alles andere sagt: Ich bin dein Freund, wir werden das nach dem Buch machen.
Nun der vollständige Code mit IE <10 Workaround:
quelle
Ein Grund, warum Ihre Skripte so langsam geladen werden könnten, ist, dass Sie alle Ihre Skripte beim Laden der Seite wie folgt ausgeführt haben:
anstatt:
Dieses zweite Skript wartet, bis der Browser Ihren gesamten Javascript-Code vollständig geladen hat, bevor er mit der Ausführung eines Ihrer Skripte beginnt, sodass der Benutzer den Eindruck hat, dass die Seite schneller geladen wurde.
Wenn Sie die Benutzererfahrung verbessern möchten, indem Sie die Ladezeit verkürzen, würde ich die Option "Ladebildschirm" nicht wählen. Meiner Meinung nach wäre das viel ärgerlicher, als wenn die Seite nur langsamer geladen würde.
quelle
Ich würde vorschlagen, dass Sie sich Modernizr ansehen . Es ist eine kleine, leichte Bibliothek, mit der Sie Ihr Javascript asynchron laden können. Mit Funktionen können Sie überprüfen, ob die Datei geladen ist, und das Skript in der von Ihnen angegebenen ausführen.
Hier ist ein Beispiel für das Laden von jquery:
quelle
Ich habe einen kleinen Beitrag geschrieben, um Ihnen dabei zu helfen. Weitere Informationen finden Sie hier https://timber.io/snippets/asynchronously-load-a-script-in-the-browser-with-javascript/ , aber ich habe angehängt die Helferklasse unten. Es wartet automatisch darauf, dass ein Skript geladen wird, und gibt anschließend ein angegebenes Fensterattribut zurück.
Die Verwendung ist wie folgt:
quelle
Vielleicht finden Sie diesen Wiki-Artikel interessant: http://ajaxpatterns.org/On-Demand_Javascript
Es wird erklärt, wie und wann eine solche Technik anzuwenden ist.
quelle
Nun,
x.parentNode
gibt das HEAD - Element, so dass Sie das Skript einfügen kurz vor dem Head - Tag. Vielleicht ist das das Problem.Versuchen Sie es
x.parentNode.appendChild()
stattdessen.quelle
Überprüfen Sie diese https://github.com/stephen-lazarionok/async-resource-loader . Es gibt ein Beispiel, das zeigt, wie JS, CSS und mehrere Dateien mit einem Schuss geladen werden.
quelle
Sie können LABJS oder RequreJS verwenden
Script Lader mag
LABJS
,RequireJS
wird die Geschwindigkeit und Qualität des Codes verbessern.quelle
Haben Sie überlegt, Fetch Injection zu verwenden? Ich habe eine Open-Source-Bibliothek namens Fetch-Inject gerollt , um solche Fälle zu behandeln. So könnte Ihr Loader mit der lib aussehen:
Nutzen Sie zur Erkennung der Abwärtskompatibilität die Funktionserkennung und greifen Sie auf XHR Injection- oder Script DOM-Elemente zurück oder fügen Sie die Tags einfach mit in die Seite ein
document.write
.quelle
Hier ist meine benutzerdefinierte Lösung zur Beseitigung von JavaScript, das das Rendern blockiert:
Kurz gesagt, es lädt alle Ihre Skripte asynchron und führt sie anschließend aus.
Github-Repo : https://github.com/mudroljub/js-async-loader
quelle
No 'Access-Control-Allow-Origin' header is present on the requested resource
Hier eine kleine ES6-Funktion, wenn jemand sie zum Beispiel in React verwenden möchte
quelle
Ich würde vorschlagen, zuerst die Dateien zu minimieren und zu prüfen, ob Sie dadurch einen ausreichend großen Geschwindigkeitsschub erhalten. Wenn Ihr Host langsam ist, können Sie versuchen, diesen statischen Inhalt auf einem CDN abzulegen.
quelle