5869 votes

Comment inclure un fichier JavaScript dans un autre fichier JavaScript ?

Y a-t-il quelque chose en JavaScript similaire à @import en CSS qui vous permet d'inclure un fichier JavaScript à l'intérieur d'un autre fichier JavaScript ?

0 votes

5072voto

e-satis Points 146299

Les anciennes versions de JavaScript n'avaient pas d'import, d'include ou de require, si bien que de nombreuses approches différentes de ce problème ont été développées.

Mais depuis 2015 (ES6), JavaScript dispose du Modules ES6 pour importer des modules dans Node.js, ce qui est également supporté par la plupart des navigateurs modernes .

Pour assurer la compatibilité avec les anciens navigateurs, des outils de construction comme Webpack y Rollup et/ou des outils de transpilation comme Babel peut être utilisé.

Modules ES6

Les modules ECMAScript (ES6) ont été supporté dans Node.js depuis la version 8.5, avec le --experimental-modules et depuis au moins Node.js v13.8.0 sans ce drapeau. Pour activer "ESM" (par opposition au système de modules de style CommonJS ["CJS"] de Node.js), vous pouvez utiliser soit "type": "module" en package.json ou donner aux fichiers l'extension .mjs . (De même, les modules écrits avec le précédent module CJS de Node.js peuvent être nommés .cjs si votre valeur par défaut est ESM).

Utilisation de package.json :

{
    "type": "module"
}

Puis module.js :

export function hello() {
  return "Hello";
}

Puis main.js :

import { hello } from './module.js';
let val = hello();  // val is "Hello";

Utilisation de .mjs vous auriez module.mjs :

export function hello() {
  return "Hello";
}

Puis main.mjs :

import { hello } from './module.mjs';
let val = hello();  // val is "Hello";

Modules ECMAScript dans les navigateurs

Les navigateurs prennent en charge le chargement direct des modules ECMAScript (sans l'aide d'outils comme Webpack). depuis Safari 10.1, Chrome 61, Firefox 60 et Edge 16. Consultez l'assistance actuelle à l'adresse suivante caniuse . Il n'est pas nécessaire d'utiliser Node.js'. .mjs les navigateurs ignorent complètement les extensions de fichiers sur modules/scripts.

<script type="module">
  import { hello } from './hello.mjs'; // Or the extension could be just `.js`
  hello('world');
</script>

// hello.mjs -- or the extension could be just `.js`
export function hello(text) {
  const div = document.createElement('div');
  div.textContent = `Hello ${text}`;
  document.body.appendChild(div);
}

Plus d'informations sur https://jakearchibald.com/2017/es-modules-in-browsers/

Importations dynamiques dans les navigateurs

Les importations dynamiques permettent au script de charger d'autres script selon les besoins :

<script type="module">
  import('hello.mjs').then(module => {
      module.hello('world');
    });
</script>

Plus d'informations sur https://developers.google.com/web/updates/2017/11/dynamic-import

Node.js require

L'ancien style de module CJS, encore largement utilisé dans Node.js, est le module module.exports / require système.

// mymodule.js
module.exports = {
   hello: function() {
      return "Hello";
   }
}

// server.js
const myModule = require('./mymodule');
let val = myModule.hello(); // val is "Hello"   

Il existe d'autres moyens pour JavaScript d'inclure des contenus JavaScript externes dans les navigateurs qui ne nécessitent pas de prétraitement.

Chargement AJAX

Vous pourriez charger un script supplémentaire avec un appel AJAX et ensuite utiliser eval pour le faire fonctionner. C'est la méthode la plus simple, mais elle est limitée à votre domaine en raison du modèle de sécurité de la sandbox JavaScript. Utilisation de eval ouvre également la porte aux bogues, aux piratages et aux problèmes de sécurité.

Chargement des données

Comme pour les importations dynamiques, vous pouvez charger un ou plusieurs scripts avec une commande fetch en utilisant des promesses pour contrôler l'ordre d'exécution des dépendances script à l'aide de l'option Récupérer Injecter bibliothèque :

fetchInject([
  'https://cdn.jsdelivr.net/momentjs/2.17.1/moment.min.js'
]).then(() => {
  console.log(`Finish in less than ${moment().endOf('year').fromNow(true)}`)
})

Chargement jQuery

El jQuery La bibliothèque fournit une fonctionnalité de chargement en une seule ligne :

$.getScript("my_lovely_script.js", function() {
   alert("Script loaded but not necessarily executed.");
});

Chargement du script dynamique

Vous pourriez ajouter une balise script avec l'URL script dans le HTML. Pour éviter la surcharge de jQuery, c'est une solution idéale.

Le script peut même résider sur un serveur différent. En outre, le navigateur évalue le code. Le site <script> peut être injecté soit dans la page web <head> ou inséré juste avant la fermeture </body> étiquette.

Voici un exemple de la façon dont cela pourrait fonctionner :

function dynamicallyLoadScript(url) {
    var script = document.createElement("script");  // create a script DOM node
    script.src = url;  // set its src to the provided URL

    document.head.appendChild(script);  // add it to the end of the head section of the page (could change 'head' to 'body' to add it to the end of the body section instead)
}

Cette fonction ajoutera un nouveau <script> à la fin de la section d'en-tête de la page, où la balise src est fixé à l'URL qui est donnée à la fonction comme premier paramètre.

Ces deux solutions sont discutées et illustrées dans JavaScript Madness : Chargement dynamique du script .

Détecter quand le script a été exécuté.

Maintenant, il y a un gros problème que vous devez connaître. Faire cela implique que vous chargez le code à distance . Les navigateurs web modernes chargeront le fichier et continueront à exécuter votre script actuel car ils chargent tout de manière asynchrone pour améliorer les performances. (Cela s'applique à la fois à la méthode jQuery et à la méthode de chargement dynamique manuel du script).

Cela signifie que si vous utilisez ces astuces directement, vous ne pourrez pas utiliser votre code nouvellement chargé la ligne suivante après avoir demandé son chargement car il sera toujours en cours de chargement.

Par exemple : my_lovely_script.js contient MySuperObject :

var js = document.createElement("script");

js.type = "text/javascript";
js.src = jsFilePath;

document.body.appendChild(js);

var s = new MySuperObject();

Error : MySuperObject is undefined

Puis vous rechargez la page en frappant F5 . Et ça marche ! Confusion...

Que faire alors ?

Eh bien, vous pouvez utiliser le hack que l'auteur suggère dans le lien que je vous ai donné. En résumé, pour les gens pressés, il utilise un événement pour exécuter une fonction callback lorsque le script est chargé. Ainsi, vous pouvez mettre tout le code utilisant la bibliothèque distante dans la fonction callback. Par exemple :

function loadScript(url, callback)
{
    // Adding the script tag to the head as suggested before
    var head = document.head;
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url;

    // Then bind the event to the callback function.
    // There are several events for cross browser compatibility.
    script.onreadystatechange = callback;
    script.onload = callback;

    // Fire the loading
    head.appendChild(script);
}

Ensuite, vous écrivez le code que vous voulez utiliser APRÈS que le script soit chargé dans une fonction lambda :

var myPrettyCode = function() {
   // Here, do whatever you want
};

Puis vous exécutez tout ça :

loadScript("my_lovely_script.js", myPrettyCode);

Notez que le script peut s'exécuter après le chargement du DOM, ou avant, selon le navigateur et si vous avez inclus la ligne script.async = false; . Il y a un excellent article sur le chargement du Javascript en général qui traite de ce sujet.

Fusion/prétraitement du code source

Comme nous l'avons mentionné au début de cette réponse, de nombreux développeurs utilisent des outils de construction/transpilation tels que Parcel, Webpack ou Babel dans leurs projets, ce qui leur permet d'utiliser la nouvelle syntaxe JavaScript, d'assurer la rétrocompatibilité avec les anciens navigateurs, de combiner des fichiers, de réduire le code, de le fractionner, etc.

0 votes

J'ai chargé la division dynamiquement en cliquant sur le menu sans charger la page en utilisant l'URL hash. Mon problème est que lorsque je clique sur la même page 2/3 fois, les js se chargent 2/3 fois. C'est pourquoi chaque événement se produit plusieurs fois. Je veux vérifier que le fichier js est déjà chargé dans le footer/head avant de l'ajouter dans ce code : var js = document.createElement("script") ; js.type = "text/javascript" ; js.src = jsFilePath ; document.body.appendChild(js) ;

13 votes

Oh mon dieu, tu viens d'écrire un papier entier ! Merci beaucoup ! Tu es une légende. :)

0 votes

Merci pour votre contribution. Y a-t-il un moyen d'insérer le script au début de l'en-tête ?

608voto

John Strickler Points 8534

Si quelqu'un cherche quelque chose de plus avancé, essayez le RequireJS . Vous bénéficierez d'avantages supplémentaires tels que la gestion des dépendances, une meilleure concurrence et éviterez la duplication (c'est-à-dire la récupération d'un script plus d'une fois).

Vous pouvez écrire vos fichiers JavaScript dans des "modules" et ensuite les référencer comme dépendances dans d'autres scripts. Ou vous pouvez utiliser RequireJS comme une simple solution "allez chercher ce scripts".

Exemple :

Définir les dépendances comme des modules :

certaines-dependances.js

define(['lib/dependency1', 'lib/dependency2'], function (d1, d2) {

     //Your actual script goes here.   
     //The dependent scripts will be fetched if necessary.

     return libraryObject;  //For example, jQuery object
});

implémentation.js est votre fichier JavaScript "principal" qui dépend de certaines-dependances.js

require(['some-dependency'], function(dependency) {

    //Your script goes here
    //some-dependency.js is fetched.   
    //Then your script is executed
});

Extrait de la GitHub README :

RequireJS charge des fichiers JavaScript simples ainsi que des fichiers plus définis. plus définis. Il est optimisé pour une utilisation dans le navigateur, y compris dans un Web Worker, mais il peut être utilisé dans d'autres environnements JavaScript, tels que Rhino et Node. Il met en œuvre l'API de module asynchrone.

RequireJS utilise les simples balises script pour charger les modules/fichiers, il doit donc permettre un débogage facile. Il peut être utilisé simplement pour charger des fichiers JavaScript existants, donc vous pouvez l'ajouter à votre projet existant sans sans avoir à réécrire vos fichiers JavaScript.

...

225voto

Kipras Points 632

En fait, il y a est un moyen de charger un fichier JavaScript pas de manière asynchrone, de sorte que vous pouvez utiliser les fonctions incluses dans votre fichier nouvellement chargé juste après son chargement, et je pense que cela fonctionne dans tous les navigateurs.

Vous devez utiliser jQuery.append() sur le <head> élément de votre page, c'est-à-dire :

$("head").append($("<script></script>").attr("src", url));

/* Note that following line of code is incorrect because it doesn't escape the
 * HTML attribute src correctly and will fail if `url` contains special characters:
 * $("head").append('<script src="' + url + '"></script>');
 */

Cependant, cette méthode présente également un problème : si une erreur se produit dans le fichier JavaScript importé, Firebug (et aussi la console d'erreurs de Firefox et Outils du développeur Chrome ) signalera son emplacement de manière incorrecte, ce qui est un gros problème si vous utilisez souvent Firebug pour repérer les erreurs JavaScript (comme je le fais). Pour une raison quelconque, Firebug n'est pas au courant du fichier nouvellement chargé, et si une erreur se produit dans ce fichier, il signale qu'elle s'est produite dans votre fichier principal. HTML et vous aurez du mal à trouver la véritable raison de l'erreur.

Mais si ce n'est pas un problème pour vous, alors cette méthode devrait fonctionner.

J'ai en fait écrit un plugin jQuery appelé $.import_js() qui utilise cette méthode :

(function($)
{
    /*
     * $.import_js() helper (for JavaScript importing within JavaScript code).
     */
    var import_js_imported = [];

    $.extend(true,
    {
        import_js : function(script)
        {
            var found = false;
            for (var i = 0; i < import_js_imported.length; i++)
                if (import_js_imported[i] == script) {
                    found = true;
                    break;
                }

            if (found == false) {
                $("head").append($('<script></script').attr('src', script));
                import_js_imported.push(script);
            }
        }
    });

})(jQuery);

Donc tout ce que vous devez faire pour importer JavaScript est :

$.import_js('/path_to_project/scripts/somefunctions.js');

J'ai également réalisé un test simple pour cela à Ejemplo .

Il comprend un main.js dans le HTML principal et ensuite le script dans le main.js utilise $.import_js() pour importer un fichier supplémentaire appelé included.js qui définit cette fonction :

function hello()
{
    alert("Hello world!");
}

Et juste après avoir inclus included.js El hello() est appelée, et vous obtenez l'alerte.

(Cette réponse fait suite au commentaire d'e-satis).

170voto

Ariel Points 2360

Une autre méthode, qui, à mon avis, est beaucoup plus propre, consiste à effectuer une requête Ajax synchrone au lieu d'utiliser un fichier de type <script> étiquette. C'est également ainsi que Node.js Les poignées comprennent.

Voici un exemple utilisant jQuery :

function require(script) {
    $.ajax({
        url: script,
        dataType: "script",
        async: false,           // <-- This is the key
        success: function () {
            // all good...
        },
        error: function () {
            throw new Error("Could not load script " + script);
        }
    });
}

Vous pouvez ensuite l'utiliser dans votre code comme vous le feriez habituellement avec un include :

require("/scripts/subscript.js");

Et être capable d'appeler une fonction à partir du script requis dans la ligne suivante :

subscript.doSomethingCool();

112voto

Imdad Points 2904

Il y a une bonne nouvelle pour vous. Très bientôt, vous serez en mesure de charger du code JavaScript facilement. Cela deviendra un moyen standard d'importer des modules de code JavaScript et fera partie du noyau JavaScript lui-même.

Il vous suffit d'écrire import cond from 'cond.js'; pour charger une macro nommée cond à partir d'un fichier cond.js .

Ainsi, vous n'avez pas besoin de vous appuyer sur un framework JavaScript ni de faire explicitement de la Ajax appels.

Se référer à :

1 votes

Sept ans plus tard, cette réponse ne fonctionne pas : "SyntaxError : import declarations may only appear at top level of a module".

0 votes

Partagez votre code ce que vous essayez de faire.

0 votes

Ok, voici le code qui fonctionne bien : function Include(jsFilePath) { var js = d.createElement("script") ; js.type = "text/javascript" ; js.src = jsFilePath ; d.body.appendChild(js) ; } // Inclure

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X