7
votes

Comment servir et charger des fichiers JavaScript de manière optimale?

J'espère que quelqu'un avec plus d'expérience avec les applications Web à l'échelle mondiale pourrait clarifier certaines questions, hypothèses et éventuels malentendus que j'ai.

Prenons un site hypothétique (quantité abondante de composants côté client / dynamique) qui comptent des centaines de milliers d'utilisateurs à l'échelle mondiale et les sources sont servies d'un endroit (disons l'Europe centrale).

  1. Si l'application dépend de la popularité de bibliothèques JavaScript, serait-elle préférable de le prendre à partir du fichier CDN Google et de la compiler en un seul fichier JS minifiée (ainsi que de tous les javascript spécifiques à l'application) ou de le charger séparément du CDN Google?
  2. Assetic vs Headjs : Il est-il plus logique de charger un seul fichier JS ou de charger tous les scripts en parallèle ( Exécution par ordre de dépendances)?

    mes hypothèses (corrigez-moi s'il vous plaît):

    Compilation de tout le code JS spécifique à l'application et local dans un fichier, à l'aide de CDNS comme Google pour les bibliothèques populaires, etc. mais en chargement de toutes ces via Headjs en parallèle semble optimal, mais je ne suis pas sûr. La compilation côté serveur des JS tiers et des JS spécifiques à une application dans un fichier semble presque vaincre le but d'utiliser le CDN puisque la bibliothèque est probablement mise en cache quelque part sur la ligne de l'utilisateur.

    Outre la mise en cache, il est probablement plus rapide de télécharger une bibliothèque tierce partie à partir de CDN de Google que le serveur central hébergeamment l'application.

    Si une nouvelle version d'une bibliothèque JS populaire est publiée avec une belle boost de performances, est testée avec l'application puis implémentée:

    • Si tout JS est compilé dans un seul fichier, chaque utilisateur devra rediriger ce fichier, même si le code de l'application n'a pas changé.
    • Si les scripts tiers sont chargés de CDNS, l'utilisateur ne dispose que de la nouvelle version du CDN (ou du cache quelque part).

      sont l'une des inquiétudes légitimes suivantes dans une situation comme celle décrite?

      • Certains utilisateurs (ou navigateurs) ne peuvent avoir qu'un certain nombre de connexions à un nom d'hôte à une fois, la récupération de certains scripts d'une tierce partie CDN résulterait d'une période de chargement globalement plus rapide.
      • Certains utilisateurs peuvent utiliser l'application dans un environnement restreint. Par conséquent, le domaine de l'application peut être listé en blanc mais pas les domaines du CDNS. (Si cela est possible, c'est une préoccupation réaliste, est-il possible d'essayer de charger à partir du CDN et de charger à partir du serveur central sur une défaillance?)

5 commentaires

Il est bon de se préoccuper de la performance, mais de mon expérience, les frais généraux de chargement JavaScript sont insignifiants par rapport à la performance de l'application elle-même, à la fois du code transactionnel de code côté client et de serveur (base de données).


@Pointy: 80% du temps de réponse de l'utilisateur final est passé sur le front fin - à OP: lisez ce lien avec soin, je fais confiance à leurs conseils.


Dans mon expérience, les performances de Googles CDN sont si bonnes que cela dépasse grandement toutes les autres préoccupations.


@Tomasznurkiewicz Je pense que je pense à la web Applications Spécifiquement, car c'est mon antécédent et c'est ce que j'ai perçu le sujet de cette question. De plus, je trouve que Yahoo! La déclaration était suffisamment vague pour être sans valeur: il n'est pas pris en charge par une sorte d'explication de ce que signifie "temps de réponse de l'utilisateur final", par exemple.


@Tomasznurkiewicz Maintenant, cela dit, j'ai effectivement vu des sites - principalement ceux avec beaucoup de contenu tiers - qui passent une quantité de temps scandaleuse à télécharger un nombre fou de scripts, d'images, de petits fichiers CSS, etc., etc. Je donne L'OP au profit du doute que s'il est inquiet de la performance, il ne fera pas de telles erreurs évidentes :-)


3 Réponses :


4
votes
  1. De nombreux petits fichiers JS sont meilleurs que peu nombreux pour de nombreuses raisons, y compris des modifications / dépendances / exigences.
  2. JavaScript / CSS / HTML et tout autre contenu statique est traité de manière très efficace par l'un des serveurs Web actuels (Apache / IIS et de nombreux autres), la plupart du temps qu'un serveur Web est plus que capable de servir des demandes 100 et 1000s / Deuxièmement, ce contenu statique est susceptible d'être mis en cache quelque part entre le client et votre (s) serveur (s).
  3. en utilisant des référentiels externes (non contrôlés) pour le code que vous souhaitez utiliser dans l'environnement de production est un non-non (pour moi et beaucoup d'autres), vous ne voulez pas une défaillance soudaine, catastrophique et irrécupérable de Votre fonctionnalité JavaScript entier JavaScript Juste parce que quelqu'un a quelque part appuyé comme commit sans réflexion ni vérification.

0 commentaires

1
votes

compiler tout le code JS spécifique à l'application / local dans un fichier, en utilisant CDNS comme Google pour les bibliothèques populaires, etc., mais le chargement de tous Ceux-ci via Headjs en parallèle semble optimal ...

Je dirais que cela est essentiellement juste. NE PAS combiner plusieurs bibliothèques externes dans un seul fichier, car elle l'apparaît que vous le savez - cela annulera la majorité des cas de navigateurs des utilisateurs ayant déjà mis en cache les ressources (individuelles) déjà.

Pour votre propre code JS spécifique à la demande, une considération que vous souhaiteriez faire est la fréquence à laquelle cela sera mis à jour. Par exemple, s'il existe un noyau de fonctionnalité qui changera rarement, mais des composants plus petits qui pourraient changer régulièrement, il pourrait être logique de ne compiler que (par lequel je suppose que vous voulez dire minifiez / compressez) le noyau dans un seul fichier tout en continuant de servir la parties plus petites au coup par coup.

Votre décision devrait également tenir compte de la taille de vos actifs JS. Si-et ceci est peu probable, mais possible - vous servez un très grand montant de JavaScript, concaténant tout dans un fichier pourrait être contre-productif, car certains clients (tels que les appareils mobiles) ont des restrictions très serrées sur ce qu'ils vont cacherons. Dans ce cas, vous feriez mieux de servir une poignée d'actifs plus petits.

Ce ne sont que des drénières aléatoires pour que vous soyez au courant. Le point principal que je voulais faire était que votre premier instinct (cité ci-dessus) est probablement la bonne approche.


1 commentaires

Merci. J'ai dit compiler parce qu'il pourrait aussi y avoir du pré-traitement sur certains actifs



8
votes

Compilation de tout le code JS spécifique à l'application / local dans un fichier

Étant donné que certains de nos objectifs clés sont de Réduisez le nombre de demandes HTTP et Minimiser la demande de demande , il s'agit d'une meilleure pratique très largement adoptée.

Le cas principal où nous pourrions envisager de ne pas le faire est dans des situations où il y a une grande chance d'invalidation de cache fréquente, c'est-à-dire lorsque nous apportons des modifications à notre code. Il y aura toujours des compromis ici: Servir un seul fichier est très susceptible d'augmenter le taux d'invalidation du cache, tout en purgeant de nombreux fichiers distincts entraînera un démarrage plus lent pour les utilisateurs avec un cache vide.

Pour cette raison, l'inlinage du bit occasionnel de javascript spécifique à la page n'est pas aussi mauvais que certains. En général, cependant, concaténant et minier votre JS dans un seul fichier est une excellente première étape.

Utiliser des CDN comme Google pour les bibliothèques populaires, etc.

Si nous parlons de bibliothèques où le code que nous utilisons est assez immuable, c'est-à-dire imputable à être soumis à une invalidation de cache, je pourrais être légèrement plus en faveur de la sauvegarde des demandes HTTP en les enveloppant dans votre fichier JS local monolithique . Cela serait particulièrement vrai pour une base de code importante fortement basée sur, par exemple une version de jQuery particulière. Dans des cas comme cette cognement, la version de la bibliothèque est presque certaine d'impliquer des modifications importantes à votre code d'application client, nier l'avantage de les garder séparés.

Néanmoins, Domaines de demande de mélange est une victoire importante , Puisque nous ne voulons pas être étrangers excessivement par les connexions maximales par capuchon de domaine. Bien sûr, un sous-domaine peut également servir également à cela, mais le domaine de Google a l'avantage d'être la cookieLessess et est probablement déjà dans le cache DNS du client.

mais chargement de tous ceux-ci via Headjs en parallèle semble optimal

Bien que l'hôte émergent de «chargeurs» javascript, nous devons garder à l'esprit que l'utilisation de la page d'impact négatif commence, car le navigateur doit aller chercher notre chargeur avant que le chargeur puisse demander au reste de notre les atouts. Mettez un autre moyen, pour un utilisateur avec un cache vide, un aller-retour complet sur le serveur est requis avant que tout chargement réel ne puisse commencer. Encore une fois, une étape "compile" peut venir à la rescousse - voir Exiger.js pour un Grande implémentation hybride.

La meilleure façon de vous assurer que vos scripts ne bloquent pas la peinture de l'interface utilisateur reste de les placer à la fin de votre HTML. Si vous préférez placez-les ailleurs, le async ou différend vous offre maintenant cette flexibilité. Tous les navigateurs modernes demandent des actifs en parallèle, alors à moins que vous n'ayez besoin de prendre en charge des saveurs particulières de client hérité, cela ne devrait pas être une considération majeure. BrowserScope Network Table est une excellente référence pour ce genre de chose. IE8 est de manière prévisible le délinquant principal, bloquant toujours les demandes d'image et d'iframe jusqu'à ce que les scripts soient chargés. Même en arrière à 3.6 Firefox a tout à fait la paralLealisant tout sauf.

Certains utilisateurs peuvent utiliser l'application dans un environnement restreint. Par conséquent, le domaine de la demande peut être listé en blanc mais pas les domaines du CDNS. (S'il est possible que c'est réaliste préoccupation, est-il possible d'essayer de charger à partir du CDN et la charge du serveur central en cas d'échec?)

Travailler si la machine client peut accéder à un hôte distant va toujours encourent de lourdes peines de performance, puisque nous devons attendre qu'il ne se connectent pas avant de pouvoir charger notre copie de réserve. Je serais beaucoup plus enclin à accueillir ces actifs localement.


5 commentaires

"Tous les navigateurs modernes demandent des actifs en parallèle, alors à moins que vous n'ayez besoin de prendre en charge des saveurs particulières de client hérité, cela ne devrait pas être une considération majeure." Pourriez-vous donner plus d'informations sur la manière dont les navigateurs modernes demandent des actifs et exécutés eux? Quels navigateurs compris dans "Tous les navigateurs modernes" ? Même si le navigateur demande aux actifs en parallèle, peut-être que Headjs serait toujours utile pour nous permettre d'indiquer explicitement l'ordre de chargement et d'exécution basé sur des dépendances?


Par exemple: vous pouvez utiliser Headjs pour charger toutes les JS spécifiques à une application et JS tiers, en parallèle. Une fois que cela est terminé, vous pouvez charger des modèles JS compilés (en arrière-plan asynchrone de manière à ce que lorsqu'une action se produise, qui nécessite le modèle de dialogue, il est déjà là et peut être rendu instantanément. Voir Twigjs ) dans l'ordre de la probabilité (qu'elle est nécessaire suivante) puis la dépendance (modèle peut hériter les uns des autres)


Dans les temps passés, les scripts bloqueraient toutes les demandes de démarrage, y compris celles des images et du CSS, jusqu'à ce que le contenu ait été téléchargé, analysé et exécuté. Peu de navigateurs dans la circulation actuelle font cela - j'ai ajouté un peu de détail à la réponse, y compris un lien vers le Table réseau de navigateurs de navigateur .


Mon outil de choix pour la gestion de la dépendance et l'optimisation du script côté client est Exiger.js , qui peut gérer l'exemple d'utilisation dans votre deuxième commentaire. Vous voulez probablement une étape compacte / minifiée pour générer la charge utile initiale, avec le code de l'application dans ce fichier pour gérer le chargement préemptif de scripts supplémentaires.


Re: "Inliner le bit occasionnel de la page spécifique à la page n'est pas aussi pervers que certains disent." Le problème avec un "bit" de script en ligne est que dans un environnement d'équipe, le script futur sera souvent ajouté au script original en ligne, tournant un peu de script en un peu de script au fil du temps. Le script en ligne peut alors faire partie de la teneur dynamique que les navigateurs ne se cachent pas. Les fichiers de script externes (