Include / require / import en javascript


On ne peut pas inclure un script dans un script en JS dans un navigateur Web. Il n’y a pas de mot clé import, include ou require.

On peut néanmoins trouver un moyen d’inclure du code en le téléchargeant et en l’incluant dans la page.

Solution 1, la bourrine

On peut faire une requête GET et un eval sur. C’est dangereux. C’est bancal. Ca marche que pour le domaine en cours. C’est pas une bonne idée. Je ne vous le montre donc pas.

Solution 2, la maline

On va créer une balise <script></script> et la faire pointer sur le fichier à télécharger. Ainsi on utilise le mécanisme naturel pour le navigateur d’include du code.

var include = function(url, callback){
 
    /* on crée une balise<script type="text/javascript"></script> */
    var script = document.createElement('script');
    script.type = 'text/javascript';
 
    /* On fait pointer la balise sur le script qu'on veut charger
       avec en prime un timestamp pour éviter les problèmes de cache
    */
 
    script.src = url + '?' + (new Date().getTime());
 
    /* On dit d'exécuter cette fonction une fois que le script est chargé */
    if (callback) {
        script.onreadystatechange = callback;
        script.onload = script.onreadystatechange;
    }
 
    /* On rajoute la balise script dans le head, ce qui démarre le téléchargement */
    document.getElementsByTagName('head')[0].appendChild(script);
}

Ca s’utilise comme ça:

include('http://adressedemonscript.com/fichier.js', function() {
    code à exécuter une fois que le script est chargé
})

La partie callback est très importante. En effet, si vous essayez d’exécuter du code après include() qui dépend du code chargé par include(), ça va foirer : le code n’est pas encore téléchargé. En effet, les navigateurs téléchargent les balises scripts en arrière plan et en parallèle :

include('http://adressedemonscript.com/fichier.js');
code à exécyter une fois que le script est chargé

Il faut donc mettre ce code dans un callback, pour garantir qu’il soit lancé quand le script a terminé de chargé.

Solution 3, la coquine

jQuery, encore et toujours, possède un raccourcis pour faire tout ça pour vous:

$('http://adressedemonscript.com/fichier.js', function() {
    code à exécuter une fois que le script est chargé
})

24 thoughts on “Include / require / import en javascript

  • Mousse

    Le mieux reste tout de même de passer par de vrais outils comme RequireJS, IncludeJs, CommonJs… qui respectes la norme des WebModules et AMD. Beaucoup plus souple et pratique.

    De plus, ta solution 2 executera la callback avant l’execution du script sur certains navigateurs (IE par exemple)

    Bonne année !

  • Sam Post author

    J’allais pester promptement contre le fait de rajouter ENCORE 20 Mo de JS mais je viens de réaliser includejs fait 800b :-)

  • Recher

    Je suis pas un cador du javascript, mais j’ai l’impression qu’il y a une accolade de trop dans le code de la solution maline :
    if (callback) {}

    (trip)

    C’est certainement du à une overdose de “free hugs”. Quand on reçoit trop d’accolades gratuites, après, on ne sait plus quoi un faire.

    Tiens ça me fait penser à l’entreprise de jeux vidéos qui avait sorti Elvira: Mistress Of the Dark. Elle s’appelait Accolade. Ah ce jeu était génial. Se faire déchirer la trachée par un loup-garou, énucléer par un vautour ou décapiter et bouillir dans une marmite, ça n’a pas de prix. En plus on voyait ses nichons (à Elvira).

    Tiens ça me fait penser à un pote qui se promenait dans les festivaux avec un T-Shirt sur lequel était écrit “Free Coït”.

    (/trip)

  • check_ca

    Ne manquerait-il pas la vieille (et assez controversée) technique du document.write() ? Elle est certes synchrone et généralement bloquante mais aussi très simple car elle ne nécessite pas de passer par un callback et est supportée par tous les navigateurs de ce siècle.

  • check_ca

    Voilà :
    function require(url) {
      document.writeln("<script src='" + url + "'><" + "/script>");
    }

    Avec un fichier test.js contenant :
    alert("Après injection : " + (typeof window.$ != "undefined"));

    Le code ci-dessous affichera “true”
    require("http://code.jquery.com/jquery.min.js");
    require("test.js");

  • Greg

    Si je ne m’abuse, document.writeln ne fonctionne que lors du parsing du DOM. Donc si on veut ajouter dynamiquement un script apres une action utilisateur par exemple, ca ne fonctionnera pas. Selon le navigateur ca donnera meme une belle page blanche.

    C’est surement une des raisons pour laquelle cette technique est controversee en effet, mais je pense que la precision est importante :)

  • check_ca

    Oui Greg, tu as raison, la précision méritait d’être faite. Mais bon, manifestement, ça n’intéresse pas l’auteur du post.

  • check_ca

    Allez parce que je suis gentil, j’ajoute quelques liens utiles relatifs au chargement dynamique des scripts en JS:
    – pourquoi il ne faut pas utiliser appendChild
    – pourquoi il ne faut pas affecter systématiquement onreadystatechnaged

  • check_ca

    Qu’ai donc dit qui mérite ce “sticker” “ERIC CARTMAN” ?

  • Greg

    Pas mal ce lien sur appendChild oui. Je suis un chanceux, je peux me passer d’IE 6 et ses bugs.

  • Sam Post author

    C’est un google translate copier/coller d’un article de stack overflow.

  • Drife

    Je peux dire une connerie (?) ?

    Si je place tout bêtement le fichier javascript “commun” dans la page qui utilise un autre fichier javascript qui a besoin de ce “commun” ?!

    Exemple:

    //a la fin du body

    C’est mal ? C’est idiot ? Ça marche pas dans tous les cas ?

    Je me sert de cette technique pour mes libs locales…

  • Drife

    Autant pour moi, faut que j’enlève les balises “scripts” ^^

    //A la fin du body

    script type="text/javascript" src="/static/js/common.js" #/script

    script type="text/javascript" src="/static/js/produit.js" #/script

  • Sam Post author

    Tout le but de l’article est d’expliquer comment le faire dynamiquement. Ceci afin par exemple de charger une ressource en fonction du comportement de l’utilisateur ou pour faire du lazy loading.

Comments are closed.

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.