Dans d'innombrables endroits en ligne, j'ai vu la recommandation d'inclure CSS avant JavaScript. Le raisonnement est généralement de cette forme :
Quand il s'agit de commander votre CSS et JavaScript, vous voulez que votre CSS vienne en premier. La raison en est que le thread de rendu possède toutes les informations de style dont il a besoin pour rendre la page. Si JavaScript inclut la priorité, le moteur JavaScript doit tout analyser avant de passer à l'ensemble de ressources suivant. Cela signifie que le fil de rendu ne peut pas afficher complètement la page, car il n'a pas tous les styles dont il a besoin.
Mes tests réels révèlent quelque chose de tout à fait différent:
Mon harnais de test
J'utilise le script Ruby suivant pour générer des retards spécifiques pour diverses ressources:
require 'rubygems'
require 'eventmachine'
require 'evma_httpserver'
require 'date'
class Handler < EventMachine::Connection
include EventMachine::HttpServer
def process_http_request
resp = EventMachine::DelegatedHttpResponse.new( self )
return unless @http_query_string
path = @http_path_info
array = @http_query_string.split("&").map{|s| s.split("=")}.flatten
parsed = Hash[*array]
delay = parsed["delay"].to_i / 1000.0
jsdelay = parsed["jsdelay"].to_i
delay = 5 if (delay > 5)
jsdelay = 5000 if (jsdelay > 5000)
delay = 0 if (delay < 0)
jsdelay = 0 if (jsdelay < 0)
# Block which fulfills the request
operation = proc do
sleep delay
if path.match(/.js$/)
resp.status = 200
resp.headers["Content-Type"] = "text/javascript"
resp.content = "(function(){
var start = new Date();
while(new Date() - start < #{jsdelay}){}
})();"
end
if path.match(/.css$/)
resp.status = 200
resp.headers["Content-Type"] = "text/css"
resp.content = "body {font-size: 50px;}"
end
end
# Callback block to execute once the request is fulfilled
callback = proc do |res|
resp.send_response
end
# Let the thread pool (20 Ruby threads) handle request
EM.defer(operation, callback)
end
end
EventMachine::run {
EventMachine::start_server("0.0.0.0", 8081, Handler)
puts "Listening..."
}
Le mini-serveur ci-dessus me permet de définir des retards arbitraires pour les fichiers JavaScript (serveur et client) et des retards CSS arbitraires. Par exemple, http://10.0.0.50:8081/test.css?delay=500
me donne un délai de 500 ms pour transférer le CSS.
J'utilise la page suivante pour tester.
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<script type='text/javascript'>
var startTime = new Date();
</script>
<link href="http://10.0.0.50:8081/test.css?delay=500" type="text/css" rel="stylesheet">
<script type="text/javascript" src="http://10.0.0.50:8081/test2.js?delay=400&jsdelay=1000"></script>
</head>
<body>
<p>
Elapsed time is:
<script type='text/javascript'>
document.write(new Date() - startTime);
</script>
</p>
</body>
</html>
Lorsque j'inclus le CSS en premier, la page prend 1,5 seconde pour s'afficher:
Lorsque j'inclus le JavaScript en premier, la page prend 1,4 seconde pour s'afficher:
J'obtiens des résultats similaires dans Chrome, Firefox et Internet Explorer. Dans Opera cependant, la commande n'a tout simplement pas d'importance.
Ce qui semble se produire, c'est que l'interpréteur JavaScript refuse de démarrer tant que tout le CSS n'est pas téléchargé. Il semble donc qu'avoir JavaScript inclut d'abord est plus efficace car le thread JavaScript obtient plus de temps d'exécution.
Suis-je en train de manquer quelque chose, la recommandation de placer les inclusions CSS avant les inclusions JavaScript n'est-elle pas correcte?
Il est clair que nous pourrions ajouter async ou utiliser setTimeout pour libérer le thread de rendu ou mettre le code JavaScript dans le pied de page, ou utiliser un chargeur JavaScript. Le point ici concerne la commande des bits JavaScript essentiels et des bits CSS dans la tête.
la source
delay=400&jsdelay=1000
etdelay=500
qui est loin de 100 ms ou 89 ms. Je suppose que je ne sais pas à quels chiffres vous faites référence.Réponses:
C'est une question très intéressante. J'ai toujours mis mes CSS
<link href="...">
avant mes JS<script src="...">
parce que "j'ai lu une fois que c'était mieux." Vous avez donc raison; il est grand temps de faire des recherches!J'ai configuré mon propre faisceau de test dans Node (code ci-dessous). Fondamentalement, je:
<head>
pour s'exécuter<body>
pour s'exécuter, ce qui est analogue àDOMReady
.Résultats
Tout d'abord, avec le fichier CSS retardé de 500 ms:
Ensuite, j'ai défini jQuery pour qu'il retarde de 500 ms au lieu du CSS:
Enfin, je mets à la fois jQuery et le CSS pour retarder par 500ms:
Conclusions
Tout d'abord, il est important de noter que je fonctionne en supposant que vous avez des scripts situés dans le
<head>
de votre document (par opposition à la fin du<body>
). Il existe différents arguments concernant la raison pour laquelle vous pouvez créer un lien vers vos scripts dans<head>
la fin du document par rapport à la fin du document, mais cela sort du cadre de cette réponse. Il s'agit strictement de savoir si<script>
s doit précéder<link>
s dans le<head>
.Dans les navigateurs DESKTOP modernes, il semble que la liaison avec CSS n'offre d' abord aucun gain de performances. Mettre CSS après le script vous apporte un gain trivial lorsque le CSS et le script sont retardés, mais vous donne des gains importants lorsque le CSS est retardé. (Montré par les
last
colonnes du premier ensemble de résultats.)Étant donné que la dernière liaison vers CSS ne semble pas nuire aux performances mais peut fournir des gains dans certaines circonstances, vous devez lier à des feuilles de style externes après avoir lié à des scripts externes uniquement sur les navigateurs de bureau si les performances des anciens navigateurs ne sont pas un problème. Lisez la suite pour la situation mobile.
Pourquoi?
Historiquement, lorsqu'un navigateur rencontrait une
<script>
balise pointant vers une ressource externe, le navigateur arrêtait d' analyser le HTML, récupérait le script, l'exécutait, puis continuait d'analyser le HTML. En revanche, si le navigateur rencontrait un<link>
pour une feuille de style externe, il continuerait d' analyser le HTML pendant qu'il récupérait le fichier CSS (en parallèle).Par conséquent, le conseil largement répété de mettre les feuilles de style en premier - elles seraient téléchargées en premier, et le premier script à télécharger pourrait être chargé en parallèle.
Cependant, les navigateurs modernes (y compris tous les navigateurs que j'ai testés ci-dessus) ont implémenté une analyse spéculative , où le navigateur "regarde vers l'avant" dans le HTML et commence à télécharger des ressources avant le téléchargement et l'exécution des scripts.
Dans les anciens navigateurs sans analyse spéculative, placer les scripts en premier affectera les performances car ils ne seront pas téléchargés en parallèle.
Prise en charge du navigateur
L'analyse spéculative a été mise en œuvre pour la première fois en: (ainsi que le pourcentage d'utilisateurs de navigateur de bureau dans le monde utilisant cette version ou une version supérieure en janvier 2012)
Au total, environ 85% des navigateurs de bureau utilisés aujourd'hui prennent en charge le chargement spéculatif. Mettre les scripts avant CSS aura une pénalité de performance sur 15% des utilisateurs dans le monde ; YMMV en fonction de l'audience spécifique de votre site. (Et rappelez-vous que ce nombre diminue.)
Sur les navigateurs mobiles, il est un peu plus difficile d'obtenir des chiffres définitifs simplement en raison de l'hétérogénéité du paysage du navigateur mobile et du système d'exploitation. Étant donné que le rendu spéculatif a été implémenté dans WebKit 525 (publié en mars 2008) et que presque tous les navigateurs mobiles intéressants sont basés sur WebKit, nous pouvons conclure que "la plupart" des navigateurs mobiles devraient le prendre en charge. Selon quirksmode , iOS 2.2 / Android 1.0 utilise WebKit 525. Je n'ai aucune idée de l'apparence de Windows Phone.
Cependant, j'ai exécuté le test sur mon appareil Android 4, et même si j'ai vu des chiffres similaires aux résultats du bureau, je l'ai connecté au fantastique nouveau débogueur à distance dans Chrome pour Android, et l'onglet Réseau a montré que le navigateur attendait en fait de télécharger le CSS jusqu'à ce que les JavaScripts soient complètement chargés - en d'autres termes, même la dernière version de WebKit pour Android ne semble pas prendre en charge l'analyse spéculative. Je soupçonne qu'il pourrait être désactivé en raison des contraintes de processeur, de mémoire et / ou de réseau inhérentes aux appareils mobiles.
Code
Pardonnez la négligence - c'était Q&D.
app.js
css.html
js.html
test.js
jquery.js était jquery-1.7.1.min.js
la source
<head>
de votre document (par opposition à la fin du<body>
)." Je soulignerais cela beaucoup plus tôt dans la réponse, comme en haut. Inclure unscript
inhead
qui fait référence à un fichier externe n'est presque jamais correct, de presque n'importe quel point de vue (certainement pas celui des performances). Je ne me souviens pas avoir dû le faire dans la vraie vie. La ligne impaire ou deux du script en ligne peut-être, mais c'est tout. Le défaut, sans très bonnes raisons contraires, devrait être la fin du corps.Il y a deux raisons principales de mettre CSS avant JavaScript.
Les anciens navigateurs (Internet Explorer 6-7, Firefox 2, etc.) bloqueraient tous les téléchargements ultérieurs lorsqu'ils ont commencé à télécharger un script. Donc, si vous les avez
a.js
suivis,b.css
ils sont téléchargés séquentiellement: d'abord a puis b. Si vous les avezb.css
suivis,a.js
ils sont téléchargés en parallèle afin que la page se charge plus rapidement.Rien n'est rendu tant que toutes les feuilles de style ne sont pas téléchargées - cela est vrai dans tous les navigateurs. Les scripts sont différents - ils bloquent le rendu de tous les éléments DOM qui se trouvent sous la balise de script dans la page. Si vous placez vos scripts dans HEAD, cela signifie que la page entière est bloquée du rendu jusqu'à ce que toutes les feuilles de style et tous les scripts soient téléchargés. Bien qu'il soit logique de bloquer tout le rendu des feuilles de style (vous obtenez donc le style correct la première fois et évitez le flash de contenu non stylisé FOUC), il n'a pas de sens de bloquer le rendu de la page entière pour les scripts. Souvent, les scripts n'affectent aucun élément DOM ou seulement une partie des éléments DOM. Il est préférable de charger les scripts aussi bas que possible dans la page, ou encore mieux de les charger de manière asynchrone.
C'est amusant de créer des exemples avec Cuzillion . Par exemple, cette page a un script dans la TÊTE, de sorte que la page entière est vierge jusqu'à ce qu'elle soit terminée. Cependant, si nous déplaçons le script à la fin du bloc BODY, l'en-tête de page s'affiche car ces éléments DOM se trouvent au-dessus de la balise SCRIPT, comme vous pouvez le voir sur cette page .
la source
async
attribut, que Steve recommande ici quand il dit "encore mieux de les charger de manière asynchrone" - stackoverflow.com/questions/1834077/…@import
directives?jQuery
+jQuery UI
+$(document).ready(function () { });
à la fin de la page? Est-ce que cela va fonctionnera- toujours comme prévu?Je n'insisterais pas trop sur les résultats que vous avez obtenus, je pense que c'est subjectif, mais j'ai une raison de vous expliquer qu'il vaut mieux mettre en CSS avant js.
Lors du chargement de votre site Web, deux scénarios se présentent:
CASE 1: écran blanc> site sans style> site style> interaction> style et site web interactif
CASE 2: écran blanc> site sans style> interaction> site style> site style et interactif
Honnêtement , je ne peux pas imaginer que quelqu'un de choisir le cas 2. Cela signifierait que les visiteurs utilisant des connexions Internet lentes seront confrontés à un site Web dépourvu de style, qui leur permettra d'interagir avec Javascript (car il est déjà chargé). En outre, le temps passé à consulter un site Web dépourvu de style serait ainsi maximisé. Pourquoi quelqu'un voudrait-il cela?
Cela fonctionne également mieux comme le dit jQuery
Lorsque les fichiers sont chargés dans le mauvais ordre (d'abord JS, puis CSS), tout code Javascript reposant sur les propriétés définies dans les fichiers CSS (par exemple la largeur ou la hauteur d'un div) ne sera pas chargé correctement. Il semble qu'avec le mauvais ordre de chargement, les propriétés correctes soient «parfois» connues de Javascript (peut-être est-ce dû à une condition de concurrence?). Cet effet semble plus ou moins important selon le navigateur utilisé.
la source
Vos tests ont-ils été effectués sur votre ordinateur personnel ou sur un serveur Web? Est-ce une page blanche, ou est-ce un système en ligne complexe avec des images, des bases de données, etc.? Vos scripts effectuent-ils une simple action d'événement de survol, ou constituent-ils un composant essentiel de la façon dont votre site Web affiche et interagit avec l'utilisateur? Il y a plusieurs choses à considérer ici, et la pertinence de ces recommandations devient presque toujours des règles lorsque vous vous aventurez dans un développement Web de haut calibre.
Le but de la règle "mettre les feuilles de style en haut et les scripts en bas" est qu'en général, c'est le meilleur moyen d'obtenir un rendu progressif optimal , ce qui est essentiel pour l'expérience utilisateur.
Tout le reste à part: en supposant que votre test est valide et que vous produisez vraiment des résultats contraires aux règles populaires, cela ne serait vraiment pas surprenant. Chaque site Web (et tout ce qu'il faut pour que tout apparaisse sur l'écran d'un utilisateur) est différent et Internet évolue constamment.
la source
J'inclus des fichiers CSS avant Javascript pour une raison différente.
Si mon Javascript doit effectuer un dimensionnement dynamique d'un élément de page (pour les cas d'angle où CSS est vraiment un élément principal à l'arrière), le chargement du CSS après que le JS est en panne peut entraîner des conditions de concurrence, où l'élément est redimensionné avant les styles CSS sont appliqués et semblent donc bizarres lorsque les styles entrent enfin en jeu. Si je charge le CSS au préalable, je peux garantir que les choses fonctionnent dans l'ordre prévu et que la mise en page finale est ce que je veux qu'elle soit.
la source
La recommandation d'inclure CSS avant JavaScript n'est-elle pas valide?
Pas si vous la traitez simplement comme une recommandation. Mais si vous la traitez comme une règle dure et rapide?, Oui, elle n'est pas valide.
Depuis https://developer.mozilla.org/en-US/docs/Web/Reference/Events/DOMContentLoaded
Il semble que vous devez savoir sur quoi s'appuie chaque script et vous assurer que l'exécution du script est retardée jusqu'à ce que l'événement de fin soit correct. Si le script ne repose que sur le DOM, il peut reprendre dans ondomready / domcontentloaded, s'il s'appuie sur des images à charger ou des feuilles de style à appliquer, alors si je lis correctement la référence ci-dessus, ce code doit être différé jusqu'à l'événement onload.
Je ne pense pas qu'une seule taille de chaussette convienne à tous, même si c'est la façon dont elles sont vendues et je sais qu'une seule taille de chaussure ne convient pas à tous. Je ne pense pas qu'il y ait une réponse définitive à laquelle charger en premier, les styles ou le script. Il s'agit plutôt d'une décision au cas par cas de ce qui doit être chargé dans quel ordre et de ce qui peut être différé jusqu'à plus tard comme n'étant pas sur le "chemin critique".
Pour parler à l'observateur qui a commenté qu'il vaut mieux retarder la capacité des utilisateurs à interagir jusqu'à ce que la feuille soit jolie. Vous êtes nombreux et vous agacez vos homologues qui ressentent le contraire. Ils sont venus sur un site pour atteindre un objectif et les retards dans leur capacité à interagir avec un site en attendant que des choses qui ne comptent pas terminer le chargement soient très frustrants. Je ne dis pas que vous vous trompez, mais seulement que vous devez savoir qu'il existe une autre faction qui ne partage pas votre priorité.
Cette question s'applique particulièrement à toutes les annonces placées sur des sites Web. Je serais ravi que les auteurs du site rendent juste des divs d'espace réservé pour le contenu de l'annonce et s'assurent que leur site était chargé et interactif avant d'injecter les annonces dans un événement de chargement. Même dans ce cas, j'aimerais voir les annonces chargées en série au lieu de toutes à la fois, car elles ont un impact sur ma capacité à faire défiler le contenu du site même pendant le chargement des annonces gonflées. Mais ce n'est que le point de vue d'une seule personne.
la source
Mise à jour 2017-12-16
Je n'étais pas sûr des tests en OP. J'ai décidé d'expérimenter un peu et j'ai fini par briser certains des mythes.
Ce n'est plus vrai . Jetez un œil à la cascade générée par Chrome 63:
C'est incorrect . La feuille de style ne bloque pas le téléchargement , mais il va bloquer l' exécution du script ( peu d' explications ici ). Jetez un œil au tableau des performances généré par Chrome 63:
Compte tenu de ce qui précède, les résultats de l'OP peuvent être expliqués comme suit:
CSS First:
JS First:
la source
The reason is that the script may want to get coordinates and other style-dependent properties of elements, like in the example above. Naturally, it has to wait for styles to load.
javascript.info/… Pourquoi la même hypothèse ne s'applique-t-elle pas en cas de JS d'abord? Cela n'a pas beaucoup de sens pour moi, l'ordre de JS exécuté ne dit rien de son objectif.Je ne sais pas exactement comment le temps de rendu de vos tests est identique à celui de votre script Java. Considérez cependant ceci
Une page de votre site fait 50k, ce qui n'est pas déraisonnable. L'utilisateur est sur la côte est tandis que votre serveur est à l'ouest. MTU n'est certainement pas à 10 km, il y aura donc quelques allers-retours. Cela peut prendre une demi-seconde pour recevoir votre page et vos feuilles de style. Typiquement (pour moi) javascript (via le plugin jquery et autres) est bien plus que CSS. Il y a aussi ce qui se passe lorsque votre connexion Internet s'étouffe à mi-chemin sur la page mais laisse ignorer cela (cela m'arrive de temps en temps et je crois que le CSS s'affiche mais je ne suis pas sûr à 100%).
Puisque css est en tête, il peut y avoir des connexions supplémentaires pour l'obtenir, ce qui signifie qu'il peut potentiellement se terminer avant la page. Quoi qu'il en soit pendant le type, le reste de la page prend et les fichiers javascript (qui sont beaucoup plus d'octets) la page n'est pas stylée, ce qui rend le site / connexion lent.
MÊME SI l'interpréteur JS refuse de démarrer jusqu'à ce que le CSS soit terminé, le temps nécessaire pour télécharger le code javascript, surtout lorsque le serveur est loin du temps CSS, ce qui rendra le site pas joli.
C'est une petite optimisation mais c'est la raison.
la source
Voici un RÉSUMÉ de toutes les principales réponses ci-dessus (ou peut-être ci-dessous plus tard :)
Pour les navigateurs modernes, placez css où vous le souhaitez. Ils analyseraient votre fichier html (qu'ils appellent l' analyse spéculative ) et commenceraient à télécharger css en parallèle avec l'analyse html.
Pour les anciens navigateurs, continuez à mettre css en haut (si vous ne voulez pas afficher d'abord une page nue mais interactive).
Pour tous les navigateurs, placez javascript le plus bas possible sur la page, car cela arrêtera l'analyse de votre html. De préférence, téléchargez-le de manière asynchrone (par exemple, appel ajax)
Il existe également des résultats expérimentaux pour un cas particulier qui prétend mettre le javascript en premier (par opposition à la sagesse traditionnelle de mettre le CSS en premier) donne de meilleures performances mais aucun raisonnement logique n'est donné pour cela, et manque de validation concernant l'applicabilité généralisée, vous pouvez donc ignorez-le pour l'instant.
Donc, pour répondre à la question: oui. La recommandation d'inclure le CSS avant JS n'est pas valide pour les navigateurs modernes. Mettez CSS où vous voulez et mettez JS vers la fin, autant que possible.
la source
Steve Souders a déjà donné une réponse définitive mais ...
Je me demande s'il y a un problème avec le test original de Sam et la répétition de Josh.
Les deux tests semblent avoir été effectués sur des connexions à faible latence où la configuration de la connexion TCP aura un coût trivial.
Comment cela affecte le résultat du test, je ne suis pas sûr et je voudrais regarder les cascades pour les tests sur une connexion à latence `` normale '' mais ...
Le premier fichier téléchargé devrait obtenir la connexion utilisée pour la page html, et le deuxième fichier téléchargé obtiendra la nouvelle connexion. (Le rinçage des premiers modifie cette dynamique, mais cela ne se fait pas ici)
Dans les navigateurs plus récents, la deuxième connexion TCP est ouverte de manière spéculative, de sorte que la surcharge de connexion est réduite / disparaît, dans les navigateurs plus anciens, cela n'est pas vrai et la deuxième connexion aura la surcharge d'être ouverte.
Comment / si cela affecte le résultat des tests, je ne suis pas sûr.
la source
Je pense que ce ne sera pas vrai pour tous les cas. Parce que css téléchargera parallèlement mais js ne peux pas. Considérez pour le même cas,
Au lieu d'avoir un seul CSS, prenez 2 ou 3 fichiers CSS et essayez-les de cette façon,
1) css..css..js 2) css..js..css 3) js..css..css
Je suis sûr que css..css..js donnera un meilleur résultat que tous les autres.
la source
Nous devons garder à l'esprit que les nouveaux navigateurs ont travaillé sur leurs moteurs Javascript, leurs analyseurs, etc., en optimisant les problèmes de code et de balisage courants de manière à ce que les problèmes rencontrés dans les anciens navigateurs tels que <= IE8 ne soient plus pertinents, pas seulement avec en ce qui concerne le balisage mais aussi l'utilisation de variables JavaScript, de sélecteurs d'éléments, etc. Je peux voir dans un avenir pas si lointain une situation où la technologie a atteint un point où les performances ne sont plus vraiment un problème.
la source
Personnellement, je ne mettrais pas trop l'accent sur une telle «sagesse populaire». Ce qui a pu être vrai dans le passé pourrait bien ne pas être vrai maintenant. Je suppose que toutes les opérations relatives à l'interprétation et au rendu d'une page Web sont entièrement asynchrones ("récupérer" quelque chose et "agir dessus" sont deux choses entièrement différentes qui pourraient être gérées par différents threads, etc. ), et en tout cas, entièrement hors de votre contrôle ou de votre préoccupation.
Je mettrais des références CSS dans la partie "tête" du document, ainsi que toute référence à des scripts externes. (Certains scripts peuvent exiger d'être placés dans le corps, et si c'est le cas, les obliger.)
Au-delà de cela ... si vous observez que "cela semble être plus rapide / plus lent que cela, sur ce / ce navigateur", traitez cette observation comme une curiosité intéressante mais non pertinente et ne la laissez pas influencer vos décisions de conception. Trop de choses changent trop vite. (Quelqu'un veut-il parier sur combien de minutes il faudra avant que l'équipe Firefox ne présente une autre version intermédiaire de son produit? Ouais, moi non plus.)
la source