C'est une question très intéressante. J'ai toujours mis mon CSS <link href="...">
s avant mon JS <script src="...">
s parce que "j'ai lu une fois que c'est mieux." Donc, vous avez raison; il est grand temps de nous faire un peu de recherche!
J'ai monté mon propre atelier de test dans le Nœud (code ci-dessous). En Gros, J'Ai:
- Fait sûr qu'il n'y a pas de mise en cache HTTP pour le navigateur aurait à faire un téléchargement complet à chaque fois qu'une page est chargée.
- Pour simuler la réalité, j'ai inclus jQuery et le H5BP CSS (donc il y a une quantité décente de script/CSS à analyser)
- Mis en place deux pages avec CSS avant de script, l'un avec CSS script après.
- Enregistré combien de temps il a fallu pour que le script externe dans l'
<head>
d'exécuter
- Enregistré combien de temps il a fallu pour que le script en ligne dans l'
<body>
à exécuter, qui est analogue DOMReady
.
- Envoi différé de CSS et/ou de script dans le navigateur par 500ms.
- Exécuté le test de 20 fois dans les 3 principaux navigateurs.
Résultats
Tout d'abord, avec le fichier CSS retardée par 500ms:
Browser: Chrome 18 | IE 9 | Firefox 9
CSS: first last | first last | first last
=======================================================
Header Exec | | |
Average | 583ms 36ms | 559ms 42ms | 565ms 49ms
St Dev | 15ms 12ms | 9ms 7ms | 13ms 6ms
------------|--------------|--------------|------------
Body Exec | | |
Average | 584ms 521ms | 559ms 513ms | 565ms 519ms
St Dev | 15ms 9ms | 9ms 5ms | 13ms 7ms
Ensuite, j'ai mis en jQuery pour retard de 500ms à la place de la CSS:
Browser: Chrome 18 | IE 9 | Firefox 9
CSS: first last | first last | first last
=======================================================
Header Exec | | |
Average | 597ms 556ms | 562ms 559ms | 564ms 564ms
St Dev | 14ms 12ms | 11ms 7ms | 8ms 8ms
------------|--------------|--------------|------------
Body Exec | | |
Average | 598ms 557ms | 563ms 560ms | 564ms 565ms
St Dev | 14ms 12ms | 10ms 7ms | 8ms 8ms
Enfin, j'ai mis les deux jQuery et CSS de retard par 500ms:
Browser: Chrome 18 | IE 9 | Firefox 9
CSS: first last | first last | first last
=======================================================
Header Exec | | |
Average | 620ms 560ms | 577ms 577ms | 571ms 567ms
St Dev | 16ms 11ms | 19ms 9ms | 9ms 10ms
------------|--------------|--------------|------------
Body Exec | | |
Average | 623ms 561ms | 578ms 580ms | 571ms 568ms
St Dev | 18ms 11ms | 19ms 9ms | 9ms 10ms
Conclusions
Tout d'abord, il est important de noter que je suis d'exploitation en vertu de l'hypothèse que vous avez des scripts situés dans l' <head>
de votre document (par opposition à la fin de l' <body>
). Il y a différents arguments de la raison pour laquelle vous pouvez accéder à vos scripts dans l' <head>
par rapport à la fin du document, mais qui est en dehors de la portée de cette réponse. C'est strictement si <script>
s doit aller de l'avant <link>
s en <head>
.
Dans les navigateurs de BUREAU moderne, il ressemble à la liaison aux feuilles de style CSS première jamais offre un gain de performance. Mettre CSS script après vous obtient une somme insignifiante de gain lorsque les deux CSS et javascript sont en retard, mais vous donne des gains importants lors de la CSS est retardée. (Illustré par l' last
colonnes dans la première série de résultats.)
Étant donné que la liaison aux feuilles de style CSS dernier ne semble pas nuire à la performance, mais peut fournir des gains dans certaines circonstances, vous devriez avoir un lien avec des feuilles de style externes après vous lien de scripts externes uniquement sur les navigateurs de bureau, si la performance de vieux navigateurs n'est pas un sujet de préoccupation. Lire la suite pour les mobiles de la situation.
Pourquoi?
Historiquement, quand un navigateur rencontré un <script>
balise pointant vers une ressource externe, le navigateur arrêter de parser le HTML, récupérer le script, exécutez-le, puis continuer de parser le HTML. En revanche, si le navigateur a rencontré un <link>
pour une feuille de style externe, il serait continuer à parser le HTML alors qu'il a cherché le fichier CSS (en parallèle).
Par conséquent, l'opinion, largement répété des conseils pour mettre les feuilles de style de la première, ils seraient télécharger en premier, et le premier script de téléchargement peuvent être chargés en parallèle.
Cependant, les navigateurs modernes (y compris tous les navigateurs que j'ai testé avec ci-dessus) ont mis en œuvre l'analyse spéculative, où le navigateur "regarde vers l'avenir" dans le HTML et commence le téléchargement de ressources, avant de scripts télécharger et exécuter.
Dans les anciens navigateurs sans spéculative de l'analyse, de mettre des scripts première affectera les performances, car ils ne télécharge pas en parallèle.
Prise En Charge Du Navigateur
Spéculative d'analyse a été mise en oeuvre: (avec le pourcentage de monde navigateur de bureau des utilisateurs à l'aide de cette version ou plus à compter de janvier 2012)
- Chrome 1 (WebKit 525) (100%)
- IE 8 (75%)
- Firefox 3.5 (96%)
- Safari 4 (99%)
- Opera 11.60 (85%)
Au total, environ 85% des navigateurs de bureau en usage aujourd'hui, le soutien spéculative de chargement. Mettre les scripts avant de CSS aura une performance pénalité de 15% des utilisateurs à l'échelle mondiale; YMMV basée sur votre site public spécifique. (Et n'oubliez pas que le nombre est en diminution.)
Sur les navigateurs mobiles, c'est un peu plus difficile à obtenir nombre définitif simplement en raison de la façon hétérogène, le navigateur mobile et OS paysage. Depuis spéculative rendu a été mis en œuvre dans WebKit 525 (sorti en mars 2008), et à peu près tous la peine navigateur mobile est basé sur WebKit, nous pouvons conclure que "la plupart" des navigateurs mobiles devraient la soutenir. Selon quirksmode, iOS 2.2/Android 1.0 utiliser WebKit 525. Je n'ai aucune idée de ce que Windows Phone ressemble.
Cependant, j'ai couru le test sur mon Android 4 appareil, et alors que j'ai vu des chiffres similaires pour le bureau des résultats, j'ai accroché jusqu'à la nouvelle fantastique débogueur distant dans Chrome pour Android, et dans l'onglet Réseau a montré que le navigateur a été réellement attendre de télécharger le fichier CSS jusqu'à ce que le Javascript complètement chargée – en d'autres termes, même la plus récente version de WebKit pour Android ne semble pas soutenir spéculative de l'analyse. Je soupçonne que c'est peut-être désactivée en raison de la CPU, de la mémoire et/ou du réseau, les contraintes inhérentes aux appareils mobiles.
Code
Pardonnez la médiocrité – c'était de la Q&D.
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);
});
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>
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>
test.js
var jsload = Date.now();
$(function() {
$.post('/result' + location.pathname.replace('.html','') + '/' + (jsload - start) + '/' + (bodyexec - start));
});
jquery.js a jquery-1.7.1.min.js