2010-08-12 7 views
4

Je travaille sur un morceau de code JavaScript qui, sous certaines conditions, lazy-charge deux différentes bibliothèques (Clicky Web Analytics et le moteur sélecteur Sizzle).Est-ce que l'insertion du même `<script>` dans le DOM provoque deux fois une deuxième requête dans n'importe quel navigateur?

Ce script est téléchargé des millions de fois par jour, donc l'optimisation des performances est une préoccupation majeure. À ce jour, je l'ai employé un couple de drapeaux comme script_loading et script_loaded pour essayer de faire en sorte que je ne charge ni bibliothèque plus d'une fois (par « charge », je veux dire demander les scripts après chargement de la page en insérant un élément dans <script> le DOM). Ma question est: Plutôt que de compter sur ces drapeaux, qui sont devenus un peu compliqués et difficiles à suivre dans mon code (pensez aux rappels et à tous les pièges du code asynchrone), est-ce que le cross-browser est sûr (c.-à-d. retour à IE 6) et ne pas nuire à la performance d'appeler simplement une fonction simple pour insérer un élément <script> chaque fois que j'atteins une branche de code qui a besoin d'une de ces bibliothèques? Ce dernier assurerait toujours que je ne charge que la bibliothèque quand j'en ai besoin, et simplifierais et réduirais le poids de mon code de base, mais je dois être absolument sûr que cela n'entraînera pas de surcroît, inutile demandes du navigateur. Mon intuition est que l'ajout d'un élément <script> plusieurs fois ne sera pas nuisible, car je suppose que les navigateurs devraient reconnaître une URL en double src et s'appuyer sur une copie en cache local. Mais, vous savez ce qui se passe quand nous supposons ...

J'espère que quelqu'un est assez familier avec le comportement de divers navigateurs modernes (et pas si modernes, comme IE 6) pour pouvoir parler à ce qui va se passer dans ce cas.

En attendant, je vais écrire un test pour essayer de répondre à cette question. Mon hésitation est juste que cela peut être difficile et fastidieux de vérifier avec certitude dans tous les navigateurs que mon script devrait supporter.

Merci d'avance pour toute aide et/ou contribution!

Répondre

2

Vous avez une autre solution.

Au point où vous insérez le nouvel élément de script dans le DOM, pourriez-vous pas faire une analyse rapide des éléments de script existant pour voir s'il y a un autre avec le même src? S'il y en a, n'en insérez pas un autre?

code Javascript sur la même page ne peut pas exécuter multithread, donc vous n'aurez pas de conditions de course au milieu de ce ou quoi que ce soit.

Sinon, vous êtes juste comptent sur le comportement de mise en cache des navigateurs actuels (et les proxies HTTP).

+0

Merci, thomasrutter! Le vôtre semble être une approche réalisable, mais je suis préoccupé par l'impact sur les performances de l'ensemble de cette traversée DOM. Mon script est chargé sur des pages très volumineuses et complexes, et il semble que l'exécution de 'document.getElementsByTagName ('script')' à chaque fois est susceptible d'avoir un effet négatif sur les performances. Mon approche actuelle complique le code, mais il suffit de vérifier une ou deux variables booléennes à chaque fois; l'approche que je propose me permettrait de mettre en cache un 'document.getElementsByTagName ('head') [0]' et d'y ajouter un seul script à chaque fois. Pensées? – Bungle

+0

Je voulais également mentionner que vous avez un bon point sur le comportement de mise en cache des navigateurs/proxies actuels. Mon approche proposée pourrait avoir un impact très négatif sur les performances pour tous les utilisateurs dont la mise en cache du navigateur est désactivée. – Bungle

+0

À propos de l'aspect performance - Je ne m'inquiéterais probablement pas trop, à moins que vous n'ayez plus de 200 éléments de script sur une page, je suppose. Ce n'est pas tant traversal que de s'appuyer sur la fonction getElementsByTagName() pour être implémenté efficacement sur n'importe quel navigateur. Si vous êtes vraiment concerné, vous pouvez maintenir votre propre liste sous la forme d'un tableau dont les scripts ont déjà été chargés (une approche que j'ai prise dans un cadre de JS). – thomasrutter

1

La page est traitée en tant que flux. Si vous chargez le même script plusieurs fois, il sera exécuté chaque fois qu'il est inclus. Évidemment, en raison du cache du navigateur, il ne sera demandé au serveur qu'une seule fois. Je voudrais rester loin de cette approche d'insertion de balises de script pour le même script plusieurs fois.

La façon dont je résoudre ce problème est d'avoir une fonction « test » pour chaque script pour voir si elle est chargée. Par exemple. pour sizzle ce serait "function() {return !! window ['Sizzle'];}". La balise de script n'est insérée que si la fonction de test renvoie false.

+0

Merci, Joeri! Votre approche de la fonction de test semble intéressante. Je vais revoir mon code pour voir si je peux résumer toutes les vérifications que je fais dans une fonction centrale pour une approche plus modulaire. – Bungle

0

Chaque fois que vous ajoutez un script à votre page, même s'il a le même src, le navigateur peut le trouver dans le cache local ou demander au serveur si le contenu est modifié.

Utilisation d'une variable pour vérifier si le script est inclus est une bonne façon de réduire la charge et il est très simple: par exemple, cela peut donner des œuvres pour vous:

var LOADED_JS=Object(); 
function js_isIncluded(name){//returns true if the js is already loaded 
    return LOADED_JS[name]!==undefined; 
} 
function include_js(name){ 
    if(!js_isIncluded(name)){ 
     YOUR_LAZY_LOADING_FUNCTION(name); 
     LOADED_JS[name]=true; 
    } 
} 

vous pouvez également obtenir tous les éléments de script et Vérifiez le src, ma solution est meilleure car elle a la vitesse et la simplicité d'un tableau de hachage et le script src a un chemin absolu même si vous le définissez avec un chemin relatif.
vous pouvez également initier le tableau avec les scripts normalement chargés (sans chargement paresseux) sur la page init pour éviter la double demande.