Dies ist eine sehr interessante Frage. Ich habe immer meine CSS <link href="...">
s vor meinem JavaScript <script src="...">
weil "ich einmal gelesen habe, dass es besser ist". Sie haben also Recht; es ist höchste Zeit, dass wir etwas recherchieren!
Ich habe mein eigenes Test-Harness in Node.js (Code unten). Im Grunde genommen, I:
- Es wurde sichergestellt, dass es kein HTTP-Caching gibt, so dass der Browser jedes Mal, wenn eine Seite geladen wird, einen vollständigen Download durchführen muss.
- Um die Realität zu simulieren, habe ich jQuery und das H5BP CSS (es gibt also eine ordentliche Menge an Skript/CSS zu parsen)
- Erstellen Sie zwei Seiten - eine mit CSS vor dem Skript, eine mit CSS nach dem Skript.
- Aufgezeichnet, wie lange das externe Skript in der
<head>
zur Ausführung
- Es wurde aufgezeichnet, wie lange es dauerte, bis das Inline-Skript in der
<body>
auszuführen, was analog ist zu DOMReady
.
- Verzögertes Senden von CSS und/oder Skript an den Browser um 500 ms.
- Ich habe den Test 20 Mal mit den drei wichtigsten Browsern durchgeführt.
Ergebnisse
Zunächst wird die CSS-Datei um 500 ms verzögert (die Einheit ist Millisekunden):
Browser: Chrome 18 | IE 9 | Firefox 9
CSS: first last | first last | first last
=======================================================
Header Exec | | |
Average | 583 36 | 559 42 | 565 49
St Dev | 15 12 | 9 7 | 13 6
------------|--------------|--------------|------------
Body Exec | | |
Average | 584 521 | 559 513 | 565 519
St Dev | 15 9 | 9 5 | 13 7
Als Nächstes habe ich jQuery auf eine Verzögerung von 500 ms anstelle von CSS eingestellt:
Browser: Chrome 18 | IE 9 | Firefox 9
CSS: first last | first last | first last
=======================================================
Header Exec | | |
Average | 597 556 | 562 559 | 564 564
St Dev | 14 12 | 11 7 | 8 8
------------|--------------|--------------|------------
Body Exec | | |
Average | 598 557 | 563 560 | 564 565
St Dev | 14 12 | 10 7 | 8 8
Schließlich habe ich ambos jQuery und das CSS um 500 ms zu verzögern:
Browser: Chrome 18 | IE 9 | Firefox 9
CSS: first last | first last | first last
=======================================================
Header Exec | | |
Average | 620 560 | 577 577 | 571 567
St Dev | 16 11 | 19 9 | 9 10
------------|--------------|--------------|------------
Body Exec | | |
Average | 623 561 | 578 580 | 571 568
St Dev | 18 11 | 19 9 | 9 10
Schlussfolgerungen
Zunächst ist es wichtig zu wissen, dass ich davon ausgehe, dass Sie Skripte im Verzeichnis <head>
Ihres Dokuments (im Gegensatz zum Ende der <body>
). Es gibt verschiedene Argumente, warum Sie auf Ihre Skripte in der <head>
gegen Ende des Dokuments, aber das würde den Rahmen dieser Antwort sprengen. Hier geht es ausschließlich darum, ob <script>
s sollte vorgehen <link>
s im <head>
.
In modernen DESKTOP-Browsern, es sieht so aus, als ob die Verknüpfung mit CSS zuerst erfolgt niemals bietet einen Leistungsgewinn. Wenn Sie CSS nach dem Skript einfügen, erhalten Sie einen geringen Gewinn, wenn sowohl CSS als auch Skript verzögert werden, aber einen großen Gewinn, wenn CSS verzögert wird. (Dies wird durch die last
Spalten in der ersten Ergebnismenge).
Angesichts der Tatsache, dass die Verknüpfung mit dem letzten CSS die Leistung nicht zu beeinträchtigen scheint, aber kann unter bestimmten Umständen Gewinne zu erzielen, Sie sollten auf externe Formatvorlagen verlinken nach Sie verlinken auf externe Skripte nur auf Desktop-Browsern wenn die Leistung älterer Browser keine Rolle spielt. Lesen Sie weiter, um mehr über die mobile Situation zu erfahren.
Warum?
Wenn ein Browser früher auf eine <script>
Tag, das auf eine externe Ressource verweist, würde der Browser stoppen das HTML analysieren, das Skript abrufen, es ausführen und dann mit dem Parsen des HTML fortfahren. Im Gegensatz dazu würde der Browser, wenn er auf ein <link>
für eine externe Formatvorlage, würde es weiter den HTML-Code zu analysieren, während die CSS-Datei (parallel) abgerufen wird.
Daher der häufig wiederholte Ratschlag, die Stylesheets zuerst zu laden - sie würden zuerst heruntergeladen, und das erste Skript, das heruntergeladen wird, könnte parallel geladen werden.
Moderne Browser (einschließlich aller Browser, die ich oben getestet habe) haben jedoch folgende Funktionen implementiert spekulatives Parsing Der Browser schaut in der HTML-Datei nach vorne und beginnt mit dem Herunterladen von Ressourcen. avant Skripte herunterladen und ausführen.
In alten Browsern ohne spekulatives Parsing beeinträchtigt das Voranstellen von Skripten die Leistung, da sie nicht parallel heruntergeladen werden können.
Browser-Unterstützung
Spekulatives Parsing wurde erstmals in implementiert: (zusammen mit dem Prozentsatz der weltweiten Nutzer von Desktop-Browsern, die diese Version oder eine höhere Version verwenden, Stand: Januar 2012)
Insgesamt unterstützen etwa 85 % der heute verwendeten Desktop-Browser spekulatives Laden. Die Verwendung von Skripten vor CSS wird bei 15 % der Nutzer zu Leistungseinbußen führen. weltweit Je nach der spezifischen Zielgruppe Ihrer Website können Sie unterschiedliche Erfahrungen machen. (Und denken Sie daran, dass diese Zahl schrumpft.)
Bei mobilen Browsern ist es etwas schwieriger, endgültige Zahlen zu erhalten, da die Landschaft der mobilen Browser und Betriebssysteme so heterogen ist. Da das spekulative Rendering in WebKit 525 (veröffentlicht im März 2008) implementiert wurde und so gut wie jeder sinnvolle mobile Browser auf WebKit basiert, können wir davon ausgehen, dass "die meisten" mobilen Browser debe es unterstützen. Laut quirksmode iOS 2.2/Android 1.0 verwenden WebKit 525. Ich habe keine Ahnung, wie Windows Phone aussieht.
Allerdings, Ich habe den Test auf meinem Android-4-Gerät durchgeführt und ähnliche Ergebnisse wie auf dem Desktop erhalten. Fern-Debugger in Chrome für Android, und Netzwerk zeigte, dass der Browser mit dem Herunterladen des CSS wartete, bis der JavaScript-Code vollständig geladen war - mit anderen Worten, selbst die neueste Version von WebKit für Android scheint kein spekulatives Parsing zu unterstützen. Ich vermute, dass diese Funktion aufgrund der CPU-, Speicher- und/oder Netzwerkbeschränkungen mobiler Geräte deaktiviert ist.
Code
Verzeihen Sie die Schlampigkeit - das war Q&D.
Archivo app.js
var express = require('express')
, app = express.createServer()
, fs = require('fs');
app.listen(90);
var file={};
fs.readdirSync('.').forEach(function(f) {
console.log(f)
file[f] = fs.readFileSync(f);
if (f != 'jquery.js' && f != 'style.css') app.get('/' + f, function(req,res) {
res.contentType(f);
res.send(file[f]);
});
});
app.get('/jquery.js', function(req,res) {
setTimeout(function() {
res.contentType('text/javascript');
res.send(file['jquery.js']);
}, 500);
});
app.get('/style.css', function(req,res) {
setTimeout(function() {
res.contentType('text/css');
res.send(file['style.css']);
}, 500);
});
var headresults={
css: [],
js: []
}, bodyresults={
css: [],
js: []
}
app.post('/result/:type/:time/:exec', function(req,res) {
headresults[req.params.type].push(parseInt(req.params.time, 10));
bodyresults[req.params.type].push(parseInt(req.params.exec, 10));
res.end();
});
app.get('/result/:type', function(req,res) {
var o = '';
headresults[req.params.type].forEach(function(i) {
o+='\n' + i;
});
o+='\n';
bodyresults[req.params.type].forEach(function(i) {
o+='\n' + i;
});
res.send(o);
});
Archivo css.html
<!DOCTYPE html>
<html>
<head>
<title>CSS first</title>
<script>var start = Date.now();</script>
<link rel="stylesheet" href="style.css">
<script src="jquery.js"></script>
<script src="test.js"></script>
</head>
<body>
<script>document.write(jsload - start);bodyexec=Date.now()</script>
</body>
</html>
Archivo js.html
<!DOCTYPE html>
<html>
<head>
<title>CSS first</title>
<script>var start = Date.now();</script>
<script src="jquery.js"></script>
<script src="test.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<script>document.write(jsload - start);bodyexec=Date.now()</script>
</body>
</html>
Archivo test.js
var jsload = Date.now();
$(function() {
$.post('/result' + location.pathname.replace('.html','') + '/' + (jsload - start) + '/' + (bodyexec - start));
});
jQuery fue jquery-1.7.1.min.js