IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

[Article] Pourquoi générer le code JavaScript est une fausse bonne idée


Sujet :

JavaScript

  1. #1
    Expert éminent
    Avatar de sekaijin
    Homme Profil pro
    Urbaniste
    Inscrit en
    Juillet 2004
    Messages
    4 205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Urbaniste
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2004
    Messages : 4 205
    Points : 9 127
    Points
    9 127
    Par défaut [Article] Pourquoi générer le code JavaScript est une fausse bonne idée
    Bonjour.

    En lisant le forum et en répondant aux questions, je me suis dit qu'une petite mise au point semblait nécessaire.

    Souvent, dans nos développements, nous avons un serveur dynamique PHP, ASP, JAVA, C#, Ruby, etc.

    Il est très facile et tentant de générer les divers éléments dont on a besoin directement avec le langage de ce serveur.

    C'est simple, ça apporte des facilités mais ce n'est pas toujours aussi efficace qu'on le pense.

    Lorsqu'on crée le code HTML de la page, on place au fur et à mesure le code JavaScript dont on a besoin en incluant directement dans celui-ci, tout comme pour le HTML, les valeurs des variables du langage hôte.
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    <?PHP
      $Message = '"Hello World!"';
      print '<script type="text/javascript">';
      print '    function confirm(message) { ..... }';
      print '</script>';
      print "<a href='#' onClick = 'return confirm(".$Message.");'>Test</a>";
    ?>

    Parmi les avantages, le regroupement de tout le code concernant un point précis. Ici la confirmation du message.
    Dans le langage hôte, nous avons la définition de la valeur,
    la génération du code JavaScript qui l'utilise
    et le code HTML qui permettra de l'invoquer.

    Autre avantage, on peut très facilement ne produire que le code JavaScript nécessaire à ce besoin. Si la fonction JavaScript à utiliser dépend d'une propriété dans le langage hôte, un simple if permet de produire la bonne fonction.

    Bref, je ne vais pas énumérer les avantages et encore moins les inconvénients.

    Mon propos est juste de montrer pourquoi cette idée est une fausse bonne idée.
    Pour cela revenons, au fonctionnement du Web, c'est-à-dire HTTP.

    1. Le client invoque une URL.
    2. Le serveur déroule son code et produit dynamiquement une source HTML.
    3. Le client reçoit cette source.
      • Il ne peut pas le mettre en cache car il est dynamique et contient des données variables.
      • Il le parse et crée le DOM correspondant.
      • Il donne à l'interpréteur JavaScript la source JavaScript qu'il contient.
    4. L'interpréteur JavaScript compile le code (partiellement) et le relie au DOM.
      • L'interpréteur ne peut mettre le code compilé en cache car il est embarqué dans une source qui n'est pas cachée.
    5. La page est disponible pour l'utilisateur.
    6. L'utilisateur active le code JavaScript par une action (un click dans l'exemple).
    7. L'interpréteur JavaScript compile si besoin le code non compilé et l'exécute.
      • Si l'action est encore invoquée, elle est juste exécutée.

    Si le client au cours de son activité revient sur la même page, on repart du début.
    Le code est régénéré, retransféré, réinterprété par le moteur HTML, recompilé pour le JavaScript et ce à chaque fois qu'on invoque l’URL.

    Peut-on gagner en efficacité ? La réponse est oui évidemment, en utilisant le protocole et la capacité du navigateur.

    La première chose à faire est de mettre le code JavaScript dans des fichiers séparés
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    function confirm(message) { ..... }
    et inclure le fichier dans la page.

    Reste l'utilisation des variables du langage hôte dans JavaScript.
    J'ai donné une solution ici, avec celle-ci il n'est plus du tout nécessaire de placer les valeurs des variables du langage hôte dans JavaScript.

    En quoi une telle solution peut-elle améliorer l'efficacité ?
    Reprenons le déroulement des opérations.

    1. Le client invoque une URL
    2. Le serveur déroule son code et produit dynamiquement une source HTML.
    3. Le client reçoit cette source.
      • Il ne peut pas la mettre en cache car elle est dynamique et contient des données variables.
      • Il la parse et crée le DOM correspondant.
      • Il charge les fichiers JavaScript liés.
      • Il met la source JavaScript dans le cache.
    4. L'interpréteur JavaScript compile le code (partiellement) et le relie au DOM.
      • L'interpréteur met en cache le code compilé.
    5. La page est disponible pour l'utilisateur.
    6. L'utilisateur active le code JavaScript par une action (un clic dans l'exemple).
    7. L'interpréteur JavaScript compile si besoin le code non compilé et l'exécute.
      • Si l'action est encore invoquée elle est juste exécutée.


    Si la page est rappelée, le fichier JavaScript n'est pas rechargé et il n'est pas recompilé.

    Du coup diront certains, on se retrouve avec un gros JavaScript qui contient tout les cas alors qu'en générant le JavaScript à la volée, je peux générer la fonction dont j'ai besoin
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <?PHP
      $Message = '"Hello World!"';
      print '<script type="text/javascript">';
      print '    function confirm(message) {';
      if ($property == 'some value' {
         print "       //ici le code JavaScript dans un cas";
      } else {
         print "       //ici le code JavaScript dans l'autre cas";
      }
      print '    }';
      print '</script>';
      print "<a href='#' onClick = 'return confirm(".$Message.");'>Test</a>";
    ?>

    C'est en fait un faux problème. Il suffit de faire plusieurs fichiers JavaScript et d'inclure le bon.
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <?PHP
      $Message = '"Hello World!"';
      print '<script type="text/javascript" src="' . $property . '.js">';
      print '</script>';
      print "<a href='#' onClick = 'return confirm" . $property . "(".$Message.");'>Test</a>";
    ?>

    On a ainsi le code précis de la fonction que l'on veut dans le JavaScript tout en bénéficiant du cache du compilateur JavaScript et du cache du navigateur.

    Cet aspect des choses peut avoir de gros effets.
    Sur de tout petits JavaScript, ça ne se voit quasiment pas.
    Mais ce n'est pas le cas lorsqu'ils se multiplient ou si le code devient plus gros.

    Ajoutez les caches réseaux dans l'affaire et la différence peut devenir énorme.

    Vous avez sûrement remarqué que certaines applications sur le net sont très lentes à démarrer la première fois et bien plus rapides par la suite.

    Imaginez une telle application dont le serveur est à l'autre bout du monde. Tout le code statique, CSS statique, images statiques est mis en cache dans des caches réseau tout au long du parcours (le proxy de l'entreprise fait aussi cela).

    Du coup, lorsqu'un autre client vient chercher une de ces ressource et que le réseau la trouve en cache dans l'acheminement de la requête, c'est cette version en cache qui est livrée. Ce n'est donc plus simplement juste entre le client et le serveur qu'on optimise ainsi les transferts mais sur toute la ligne.

    Avec JavaScript, il y a en plus le cache du code compilé qui apporte un réel confort à l'utilisateur. L'application devient beaucoup plus fluide et réactive.

    A+JYT

  2. #2
    Rédacteur

    Avatar de Bovino
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2008
    Messages
    23 647
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2008
    Messages : 23 647
    Points : 91 418
    Points
    91 418
    Billets dans le blog
    20
    Par défaut
    Merci pour cette analyse particulièrement intéressante !
    Pas de question technique par MP !
    Tout le monde peut participer à developpez.com, vous avez une idée, contactez-moi !
    Mes formations video2brain : La formation complète sur JavaScriptJavaScript et le DOM par la pratiquePHP 5 et MySQL : les fondamentaux
    Mon livre sur jQuery
    Module Firefox / Chrome d'intégration de JSFiddle et CodePen sur le forum

  3. #3
    Membre éclairé

    Femme Profil pro
    Experte JS / Conseillère en best practices / Chercheuse en programmation
    Inscrit en
    Octobre 2007
    Messages
    741
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Experte JS / Conseillère en best practices / Chercheuse en programmation
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2007
    Messages : 741
    Points : 808
    Points
    808
    Par défaut
    Ne serait-ce pas pas mieux d'orienter vers une solution de génération, à la volée, en DOM PHP? (avec un cache PHP, bien entendu)

    'fin, c'est ce que je fais...
    Afin d'obtenir plus facilement de l'aide, n'hésitez pas à poster votre code de carte bancaire

    Mon GitHub

    Une alternative à jQuery, Angular, Vue.js, React, ... ? Testez anticore, en quelques secondes à peine !
    (Contributions bienvenues)

  4. #4
    Expert éminent
    Avatar de sekaijin
    Homme Profil pro
    Urbaniste
    Inscrit en
    Juillet 2004
    Messages
    4 205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Urbaniste
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2004
    Messages : 4 205
    Points : 9 127
    Points
    9 127
    Par défaut
    non car le cache php est côté serveur le client devra donc toujours recompiler le code js.

    De plus pas de cache réseau dans ce cas.

    encore une fois mon propos est de sensibiliser.

    mieux vaut faire ses choix en connaissance de cause.

    A+JYT

  5. #5
    Membre éclairé

    Femme Profil pro
    Experte JS / Conseillère en best practices / Chercheuse en programmation
    Inscrit en
    Octobre 2007
    Messages
    741
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Experte JS / Conseillère en best practices / Chercheuse en programmation
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Octobre 2007
    Messages : 741
    Points : 808
    Points
    808
    Par défaut
    Si le fichier servi depuis le cache de PHP est toujours le même qu'à la visite précédente, pourquoi serait rechargé et recompilé, côté client?

    La source étant la même (domaine, url, fichier, etc.), le navigateur doit aller le rechercher en cache, non?
    Afin d'obtenir plus facilement de l'aide, n'hésitez pas à poster votre code de carte bancaire

    Mon GitHub

    Une alternative à jQuery, Angular, Vue.js, React, ... ? Testez anticore, en quelques secondes à peine !
    (Contributions bienvenues)

  6. #6
    Expert éminent
    Avatar de sekaijin
    Homme Profil pro
    Urbaniste
    Inscrit en
    Juillet 2004
    Messages
    4 205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Urbaniste
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2004
    Messages : 4 205
    Points : 9 127
    Points
    9 127
    Par défaut
    Si la page est dynamique le navigateur ne la mets pas en cache car sinon il ne pourrait avoir la bonne version à chaque appel.

    ne la mettant pas en cache il doit réinterprété la rechargé.
    ensuite (en cache ou pas) le navigateur interprète le code HTML de la page. et si celle-ci contient du js le js est compilé.

    si le script est statique et lié à la page
    le navigateur met en cache le script lorsqu'il interprète le HTML.
    puis il le compile et mets la version compilé en cache.

    à l'appel suivant que la page soit dynamique ou pas il réinterprète le HTML mais va cherché le JS déjà compilé dans le cache.

    agir côté serveur ne change donc rien.

    mais l'un n'empêche pas l'autre. lorsqu'on travail à la fluidité de son application il faut agir à tout les niveaux.

    lorsque l'application est complexe et qu'il y a beaucoup d'éléments à échanger. il faut penser aux caches serveur (php) aux caches statiques des frontaux (java) aux caches réseau et proxies, au cache fichier du navigateur, au cache du compilateur js.

    généré du js à la volé peut être intéressant. Mais parfois ça peut aussi être contre productif.

    imagine que dans deux cas une fonction foo fasse deux chose différente. pour simplifier la vie et en pensant qu'ainsi tu ne produit que js dont tu a besoin tu décide de produire le code de foo à la volé.
    à chaque appel foo ne contient que le code nécessaire.

    foo étant un fonction complexe tu préfère ça à deux fonction foo1 et foo2 te disant qu'ainsi tu ne vas pas charger coté navigateur deux grosse fonction.

    tout ce discours semble cohérent et montrer que c'est optimal.

    en fait ton client va chargé à chaque fois un des deux code foo le compiler et l'interpréter.

    si tu avais fais deux fonction foo1 et foo2 statiques effectivement le premier chargement serait plus lourd tout comme la compilation. mais ensuite ton client ne fait qu'utiliser ce qu'il a déjà.

    il est évident que suivant la taille du code et le nombre de fois ou il est utilisé
    les avantage d'une solution ou de l'autre changent.

    pour une fonction utilisé une fois ça ne change rien.
    pour une grosse fonction ou un grand nombre de petites fonctions utilisée des centaines de fois ça change tout.


    dans la vrais vie on est quelque part entre les deux et il n'est pas évident de percevoir l'impact.

    pour finir
    lorsqu'on génère un contenus dynamiquement mais avec les headers qui permettent la mise en cache. pour le client c'est comme une ressource statique. le client ne la redemandera pas. (on utilise souvent cela en java) mais dans ce cas le contenus de la ressource n'est pas dynamique.

    A+JYT

  7. #7
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 1
    Points : 1
    Points
    1
    Par défaut
    Il y a quelque chose que j'ai du mal à comprendre, comment le client distingue une ressource dynamique d'une ressource statique ?

  8. #8
    Expert éminent
    Avatar de sekaijin
    Homme Profil pro
    Urbaniste
    Inscrit en
    Juillet 2004
    Messages
    4 205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Urbaniste
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2004
    Messages : 4 205
    Points : 9 127
    Points
    9 127
    Par défaut
    dans l'entête de la réponse

  9. #9
    Membre éprouvé
    Avatar de beegees
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2004
    Messages
    3 610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2004
    Messages : 3 610
    Points : 1 277
    Points
    1 277
    Par défaut
    Merci, très intéressant ton article.

  10. #10
    Expert éminent
    Avatar de sekaijin
    Homme Profil pro
    Urbaniste
    Inscrit en
    Juillet 2004
    Messages
    4 205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Urbaniste
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2004
    Messages : 4 205
    Points : 9 127
    Points
    9 127
    Par défaut
    petite précision sur ressource statique et ressource dynamique

    ce sont les headers de la réponse qui permettent au navigateur de décider si c'est statique ou dynamique.

    un fichier sur le serveur servit par http est par défaut statique.
    (à moins que httpd soit configuré différemment)

    un serveur dynamique php java etc.
    produit lui par défaut des ressources dynamiques. (l'entête est par défaut pas de cache)

    mais comme ils sont programmable le développeur peut choisir de rendre une ressource produite dynamiquement, statique en positionnant les headers de la réponse.

    dans ce dernier cas le client considère la ressource comme statique.

    on peut se poser la question lorsqu'il s'agit d'une ressource javascript du pourquoi générer avec un serveur dynamique un js statique.

    généralement lorsqu'on produit dynamiquement une ressource c'est justement parce son contenu risque de changer régulièrement.
    si on position les headers pour la rendre statique (vu du client) ce contenu ne sera pas rechargé du coup pourquoi la produire dynamiquement ?

    il y a là une espèce de contradiction.

    il arrive que l'on produise des ressources dynamiquement mais celles-ci changeant très peu on positionne le header pour les montrer comme statique. c'est le cas des blog par exemple. la page d'un article ne change pas à chaque appel.

    mais pour du javascript ?
    soit le code change souvent. (je ne connais pas de cas typique)

    soit il ne change pas du tout. ce qui change ce sont les données.
    mieux vaut donc générer les ressources pour les données dynamiquement et le code statiquement.

    A+JYT

  11. #11
    Expert éminent
    Avatar de Benjamin Delespierre
    Profil pro
    Développeur Web
    Inscrit en
    Février 2010
    Messages
    3 929
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Février 2010
    Messages : 3 929
    Points : 7 762
    Points
    7 762
    Par défaut
    On peut d'ailleurs ajouter qu'il est possible d'envoyer des headers 304 pour faire comprendre au navigateur qu'une ressource pourtant générée dynamiquement pas PHP n'a pas évolué. On se sert pour cela du Last-Modified et du etag envoyés par le navigateur pour identifier la ressource mise en cache.

    Les explications sont disponibles ici: http://alexandre.alapetite.fr/doc-alex/php-http-304/

    On peut donc toujours faire générer ce qu'on veut par PHP et conserver le bénéfice du cache du navigateur. Ce qui est terriblement pratique dans le cadre d'émission de flux RSS.

    Cela étant, je ne remets pas en cause la pertinence de cet article, je suis de ceux qui pensent que le JavaScript et le CSS ne doivent pas être générés dynamiquement. Je tenais juste à ajouter mon grain de sel

  12. #12
    Nouveau Candidat au Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2014
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Santé

    Informations forums :
    Inscription : Mars 2014
    Messages : 1
    Points : 1
    Points
    1
    Par défaut euh...
    Bonjour les gars,

    Je suis une purge en javasrcipt, mais ce sujet m'intéresse beaucoup:
    dans un cms que je ne nommerai pas (prestashop), j'essaye d'optimiser le code de mes pages, mais les entêtes sont polluées par des script JS en vrac.
    Dans le module on à une variable ($src) qui contient le contenu du code javascript avec un mélange de variable PHP. Le module retourne cette variable et le script est affiché dans l'entête de ma page html générée.

    Voici ma question:
    Avec ce que nous amontré le grand Guru Sekaijin, comment je passe de:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    var ajaxUrl = '".$this->_path."js/ajax/fichier.php'; var Currency = '".$currency->id."'; var Path = '".$this->_path."'; 
    à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <script type="text/javascript" src="dossier/lefichierquicontienttoutca.js"></script>
    En lisant de post je me suis dis que l'on pouvait le faire, me trompe-je ?

Discussions similaires

  1. Réponses: 21
    Dernier message: 20/09/2009, 12h10
  2. Executer du code javascript dans une var
    Par Moustico dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 13/07/2009, 12h22
  3. intégration de code javascript dans une page asp.net
    Par Je-cherche-pfe dans le forum Général Dotnet
    Réponses: 1
    Dernier message: 06/09/2007, 17h10
  4. problème de code javascript pour une vue 360°
    Par tomguiss dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 14/03/2006, 22h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo