Existe-t-il quelque chose en JavaScript similaire à @import en CSS qui vous permet d'inclure un fichier JavaScript dans un autre fichier JavaScript?

5110
Alec Smart 4 juin 2009 à 15:59

29 réponses

Meilleure réponse

Les anciennes versions de JavaScript n'avaient pas d'importation, d'inclusion ou d'exigence, donc de nombreuses approches différentes de ce problème ont été développées.

Mais depuis 2015 (ES6), JavaScript a la norme Modules ES6 standard pour importer des modules dans Node.js , également pris en charge par les navigateurs les plus modernes.

Pour la compatibilité avec les anciens navigateurs, créez des outils comme Webpack et Rollup et / ou des outils de transpilation comme Babel peuvent être utilisés.

Modules ES6

Les modules ECMAScript (ES6) sont pris en charge dans Node.js depuis la version 8.5, avec le {{ X0}} flag, et depuis au moins Node.js v13.8.0 sans le flag. Pour activer "ESM" (par rapport au système de modules de style CommonJS précédent ["CJS"] de Node.js), vous devez utiliser "type": "module" dans package.json ou donner l'extension aux fichiers .mjs. (De même, les modules écrits avec le module CJS précédent de Node.js peuvent être nommés .cjs si votre valeur par défaut est ESM.)

En utilisant package.json:

{
    "type": "module"
}

Alors module.js:

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

Alors main.js:

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

Avec .mjs, vous auriez module.mjs:

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

Alors main.mjs:

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

Modules ECMAScript dans les navigateurs

Les navigateurs ont pris en charge le chargement direct des modules ECMAScript (aucun outil tel que Webpack requis) depuis Safari 10.1, Chrome 61, Firefox 60 et Edge 16. Vérifiez la prise en charge actuelle sur caniuse. Il n'est pas nécessaire d'utiliser l'extension .mjs de Node.js; les navigateurs ignorent complètement les extensions de fichiers sur les modules / scripts.

<script type="module">
  import { hello } from './hello.mjs'; // Or it could be simply `hello.js`
  hello('world');
</script>
// hello.mjs -- or it could be simply `hello.js`
export function hello(text) {
  const div = document.createElement('div');
  div.textContent = `Hello ${text}`;
  document.body.appendChild(div);
}

En savoir plus sur https://jakearchibald.com/2017/es-modules-in-browsers /

Importations dynamiques dans les navigateurs

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

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

En savoir plus sur https://developers.google.com/web/updates/ 2017/11 / import-dynamique

Node.js nécessite

L'ancien style de module CJS, encore largement utilisé dans Node.js, est le module.exports / {{X1 }} 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 façons pour JavaScript d'inclure du contenu JavaScript externe dans les navigateurs qui ne nécessitent pas de prétraitement.

Chargement AJAX

Vous pouvez charger un script supplémentaire avec un appel AJAX puis utiliser eval pour l'exécuter. C'est le moyen le plus simple, mais il est limité à votre domaine en raison du modèle de sécurité JavaScript sandbox. L'utilisation de eval ouvre également la porte à des bugs, des hacks et des problèmes de sécurité.

Récupérer le chargement

Comme Dynamic Imports, vous pouvez charger un ou plusieurs scripts avec un appel fetch en utilisant des promesses pour contrôler l'ordre d'exécution des dépendances de script en utilisant le Fetch Inject 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

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

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

Chargement de script dynamique

Vous pouvez ajouter une balise de script avec l'URL du script dans le code HTML. Pour éviter les frais généraux de jQuery, c'est une solution idéale.

Le script peut même résider sur un autre serveur. De plus, le navigateur évalue le code. La balise <script> peut être injectée dans la page Web <head> ou insérée juste avant la balise de fermeture </body>.

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 une nouvelle balise <script> à la fin de la section d'en-tête de la page, où l'attribut src est défini sur 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 de script dynamique.

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

Maintenant, il y a un gros problème que vous devez connaître. Cela implique que vous chargez le code à distance . Les navigateurs Web modernes chargeront le fichier et continueront d'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 manuel de script dynamique.)

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

Ensuite, vous rechargez la page en appuyant sur F5 . Et il fonctionne! Déroutant...

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 personnes pressées, il utilise un événement pour exécuter une fonction de rappel lorsque le script est chargé. Vous pouvez donc mettre tout le code à l'aide de la bibliothèque distante dans la fonction de rappel. 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 souhaitez utiliser APRÈS que le script est chargé dans une fonction lambda:

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

Ensuite, vous exécutez tout cela:

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 Javascript en général qui en discute.

Fusion / prétraitement du code source

Comme mentionné en haut de cette réponse, de nombreux développeurs utilisent des outils de construction / transpilation comme Parcel, Webpack ou Babel dans leurs projets, leur permettant d'utiliser la syntaxe JavaScript à venir, de fournir une compatibilité descendante pour les anciens navigateurs, de combiner des fichiers, de réduire, effectuer le fractionnement de code, etc.

4408
T.J. Crowder 21 mars 2020 à 09:09

Une autre façon, qui à mon avis est beaucoup plus propre, est de faire une requête Ajax synchrone au lieu d'utiliser une balise <script>. C'est également la façon dont Node.js gère les inclus.

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 utiliseriez habituellement un include:

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

Et pouvoir appeler une fonction à partir du script requis sur la ligne suivante:

subscript.doSomethingCool(); 
154
Peter Mortensen 28 sept. 2013 à 12:55

Dans le cas où vous utilisez des Web Workers et souhaitez inclure des scripts supplémentaires dans la portée de l'ouvrier, les autres réponses fournies sur l'ajout de scripts à la balise head, etc. ne fonctionneront pas pour vous.

Heureusement, les Web Workers ont leur propre fonction importScripts qui est une fonction globale dans le cadre du Web Worker, native du navigateur lui-même car il fait partie de la spécification.

Alternativement, en tant que deuxième réponse la plus votée à votre question met en évidence, RequireJS peut également gérer l'inclusion de scripts dans un Web Worker (appelant probablement importScripts lui-même, mais avec quelques autres fonctionnalités utiles).

16
Community 23 mai 2017 à 12:34

J'ai eu un problème simple, mais j'ai été déconcerté par les réponses à cette question.

J'ai dû utiliser une variable (myVar1) définie dans un fichier JavaScript (myvariables.js) dans un autre fichier JavaScript (main.js).

Pour cela, j'ai fait comme ci-dessous:

Chargé le code JavaScript dans le fichier HTML, dans l'ordre correct, myvariables.js d'abord, puis main.js:

<html>
    <body onload="bodyReady();" >

        <script src="myvariables.js" > </script>
        <script src="main.js" > </script>

        <!-- Some other code -->
    </body>
</html>

Fichier: myvariables.js

var myVar1 = "I am variable from myvariables.js";

Fichier: main.js

// ...
function bodyReady() {
    // ...
    alert (myVar1);    // This shows "I am variable from myvariables.js", which I needed
    // ...
}
// ...

Comme vous l'avez vu, j'ai dû utiliser une variable dans un fichier JavaScript dans un autre fichier JavaScript, mais je n'avais pas besoin d'en inclure une dans un autre. J'avais juste besoin de m'assurer que le premier fichier JavaScript était chargé avant le deuxième fichier JavaScript et que les variables du premier fichier JavaScript sont accessibles dans le deuxième fichier JavaScript, automatiquement.

Cela m'a sauvé la journée. J'espère que ça aide.

17
Peter Mortensen 11 déc. 2016 à 09:45

Si quelqu'un recherche quelque chose de plus avancé, essayez RequireJS. Vous obtiendrez des avantages supplémentaires tels que la gestion des dépendances, une meilleure simultanéité 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", puis les référencer en tant que dépendances dans d'autres scripts. Ou vous pouvez utiliser RequireJS comme une simple solution "allez chercher ce script".

Exemple:

Définissez les dépendances en tant que modules:

some-dependency.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
});

implementation.js est votre fichier JavaScript "principal" qui dépend de some-dependency.js

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

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

Extrait du GitHub LISEZMOI:

RequireJS charge des fichiers JavaScript simples ainsi que des modules 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, comme Rhino et Node. Il implémente l'API du module asynchrone.

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

...

565
Peter Mortensen 28 sept. 2013 à 13:11

Voici une version synchrone sans jQuery :

function myRequire( url ) {
    var ajax = new XMLHttpRequest();
    ajax.open( 'GET', url, false ); // <-- the 'false' makes it synchronous
    ajax.onreadystatechange = function () {
        var script = ajax.response || ajax.responseText;
        if (ajax.readyState === 4) {
            switch( ajax.status) {
                case 200:
                    eval.apply( window, [script] );
                    console.log("script loaded: ", url);
                    break;
                default:
                    console.log("ERROR: script not loaded: ", url);
            }
        }
    };
    ajax.send(null);
}

Notez que pour obtenir cet inter-domaine fonctionnel, le serveur devra définir l'en-tête allow-origin dans sa réponse.

53
Flimm 18 juin 2015 à 14:44

J'ai écrit un module simple qui automatise le travail d'importation / inclusion de scripts de module en JavaScript. Pour une explication détaillée du code, reportez-vous à l'article de blog JavaScript nécessite / importe / inclut des modules .

// ----- USAGE -----

require('ivar.util.string');
require('ivar.net.*');
require('ivar/util/array.js');
require('http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js');

ready(function(){
    //Do something when required scripts are loaded
});

    //--------------------

var _rmod = _rmod || {}; //Require module namespace
_rmod.LOADED = false;
_rmod.on_ready_fn_stack = [];
_rmod.libpath = '';
_rmod.imported = {};
_rmod.loading = {
    scripts: {},
    length: 0
};

_rmod.findScriptPath = function(script_name) {
    var script_elems = document.getElementsByTagName('script');
    for (var i = 0; i < script_elems.length; i++) {
        if (script_elems[i].src.endsWith(script_name)) {
            var href = window.location.href;
            href = href.substring(0, href.lastIndexOf('/'));
            var url = script_elems[i].src.substring(0, script_elems[i].length - script_name.length);
            return url.substring(href.length+1, url.length);
        }
    }
    return '';
};

_rmod.libpath = _rmod.findScriptPath('script.js'); //Path of your main script used to mark
                                                   //the root directory of your library, any library.


_rmod.injectScript = function(script_name, uri, callback, prepare) {

    if(!prepare)
        prepare(script_name, uri);

    var script_elem = document.createElement('script');
    script_elem.type = 'text/javascript';
    script_elem.title = script_name;
    script_elem.src = uri;
    script_elem.async = true;
    script_elem.defer = false;

    if(!callback)
        script_elem.onload = function() {
            callback(script_name, uri);
        };
    document.getElementsByTagName('head')[0].appendChild(script_elem);
};

_rmod.requirePrepare = function(script_name, uri) {
    _rmod.loading.scripts[script_name] = uri;
    _rmod.loading.length++;
};

_rmod.requireCallback = function(script_name, uri) {
    _rmod.loading.length--;
    delete _rmod.loading.scripts[script_name];
    _rmod.imported[script_name] = uri;

    if(_rmod.loading.length == 0)
        _rmod.onReady();
};

_rmod.onReady = function() {
    if (!_rmod.LOADED) {
        for (var i = 0; i < _rmod.on_ready_fn_stack.length; i++){
            _rmod.on_ready_fn_stack[i]();
        });
        _rmod.LOADED = true;
    }
};

_.rmod = namespaceToUri = function(script_name, url) {
    var np = script_name.split('.');
    if (np.getLast() === '*') {
        np.pop();
        np.push('_all');
    }

    if(!url)
        url = '';

    script_name = np.join('.');
    return  url + np.join('/')+'.js';
};

//You can rename based on your liking. I chose require, but it
//can be called include or anything else that is easy for you
//to remember or write, except "import", because it is reserved
//for future use.
var require = function(script_name) {
    var uri = '';
    if (script_name.indexOf('/') > -1) {
        uri = script_name;
        var lastSlash = uri.lastIndexOf('/');
        script_name = uri.substring(lastSlash+1, uri.length);
    } 
    else {
        uri = _rmod.namespaceToUri(script_name, ivar._private.libpath);
    }

    if (!_rmod.loading.scripts.hasOwnProperty(script_name)
     && !_rmod.imported.hasOwnProperty(script_name)) {
        _rmod.injectScript(script_name, uri,
            _rmod.requireCallback,
                _rmod.requirePrepare);
    }
};

var ready = function(fn) {
    _rmod.on_ready_fn_stack.push(fn);
};
12
Peter Mortensen 19 oct. 2014 à 18:26
var js = document.createElement("script");

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

document.body.appendChild(js);
12
Spudley 22 août 2012 à 06:44

Cela devrait faire:

xhr = new XMLHttpRequest();
xhr.open("GET", "/soap/ajax/11.0/connection.js", false);
xhr.send();
eval(xhr.responseText);
21
Peter Mortensen 2 nov. 2014 à 13:50

Il existe plusieurs façons d'implémenter des modules en Javascript, voici les 2 plus populaires:

Modules ES6

Les navigateurs ne prennent pas encore en charge ce système de modulation, donc pour pouvoir utiliser cette syntaxe, vous devez utiliser un bundler comme webpack. Il est préférable d'utiliser un bundler de toute façon, car cela peut combiner tous vos différents fichiers en un seul (ou en couple). Cela servira les fichiers du serveur vers le client plus rapidement car chaque requête HTTP est accompagnée d'une surcharge associée. Ainsi, en réduisant la demande HTTP globale, nous améliorons les performances. Voici un exemple de modules ES6:

// main.js file

export function add (a, b) {
  return a + b;
}

export default function multiply (a, b) {
  return a * b;
}


// test.js file

import {add}, multiply from './main';   // for named exports between curly braces {export1, export2}
                                        // for default exports without {}

console.log(multiply(2, 2));  // logs 4

console.log(add(1, 2));  // logs 3

CommonJS (utilisé dans NodeJS)

Ce système de modulation est utilisé dans NodeJS. Vous ajoutez essentiellement vos exportations à un objet appelé module.exports. Vous pouvez ensuite accéder à cet objet via un require('modulePath'). L'important ici est de réaliser que ces modules sont mis en cache, donc si vous require() un certain module deux fois, il retournera le module déjà créé.

// main.js file

function add (a, b) {
  return a + b;
}

module.exports = add;  // here we add our add function to the exports object


// test.js file

const add = require('./main'); 

console.log(add(1,2));  // logs 3
10
Willem van der Veen 10 août 2018 à 17:11

Il y a une bonne nouvelle pour toi. Très bientôt, vous pourrez charger facilement du code JavaScript. Il 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.

Vous n'avez donc pas à vous fier à un framework JavaScript ni à effectuer explicitement des appels Ajax.

Faire référence à:

100
Peter Mortensen 19 oct. 2014 à 18:05

Voici la version généralisée de la façon dont Facebook le fait pour son bouton J'aime omniprésent:

<script>
  var firstScript = document.getElementsByTagName('script')[0],
      js = document.createElement('script');
  js.src = 'https://cdnjs.cloudflare.com/ajax/libs/Snowstorm/20131208/snowstorm-min.js';
  js.onload = function () {
    // do stuff with your dynamically loaded script
    snowStorm.snowColor = '#99ccff';
  };
  firstScript.parentNode.insertBefore(js, firstScript);
</script>

Si cela fonctionne pour Facebook, cela fonctionnera pour vous.

La raison pour laquelle nous recherchons le premier élément script au lieu de head ou body est parce que certains navigateurs n'en créent pas s'il est manquant, mais nous avons la garantie d'avoir un {{X3 }} élément - celui-ci. En savoir plus sur http://www.jspatterns.com/the-ridiculous- cas-d'ajout d'un élément de script /.

43
Dan Dascalescu 8 juil. 2015 à 02:48

Si vous voulez en pur JavaScript, vous pouvez utiliser document.write.

document.write('<script src="myscript.js" type="text/javascript"></script>');

Si vous utilisez la bibliothèque jQuery, vous pouvez utiliser la méthode $.getScript.

$.getScript("another_script.js");
37
K.Dᴀᴠɪs 30 mars 2018 à 21:20

Si votre intention de charger le fichier JavaScript est à l'aide des fonctions du fichier importé / inclus , vous pouvez également définir un objet global et définir les fonctions comme éléments d'objet. Par exemple:

Global.js

A = {};

File1.js

A.func1 = function() {
  console.log("func1");
}

File2.js

A.func2 = function() {
  console.log("func2");
}

Main.js

A.func1();
A.func2();

Vous devez juste être prudent lorsque vous incluez des scripts dans un fichier HTML. L'ordre doit être comme ci-dessous:

<head>
  <script type="text/javascript" src="global.js"></script>
  <script type="text/javascript" src="file1.js"></script>
  <script type="text/javascript" src="file2.js"></script>
  <script type="text/javascript" src="main.js"></script>
</head>
25
Peter Mortensen 11 déc. 2016 à 09:42

Il existe également Head.js. Il est très facile de gérer:

head.load("js/jquery.min.js",
          "js/jquery.someplugin.js",
          "js/jquery.someplugin.css", function() {
  alert("Everything is ok!");
});

Comme vous le voyez, c'est plus facile que Require.js et aussi pratique que la méthode $.getScript de jQuery. Il dispose également de fonctionnalités avancées, telles que le chargement conditionnel, la détection de fonctionnalités et bien plus.

10
Peter Mortensen 19 oct. 2014 à 18:18

Il existe de nombreuses réponses possibles à cette question. Ma réponse est évidemment basée sur un certain nombre d'entre eux. C'est ce que je me suis retrouvé après avoir lu toutes les réponses.

Le problème avec $.getScript et vraiment toute autre solution qui nécessite un rappel lorsque le chargement est terminé est que si vous avez plusieurs fichiers qui l'utilisent et dépendent les uns des autres, vous n'avez plus de moyen de savoir quand tous les scripts ont été chargés (une fois qu'ils sont imbriqués dans plusieurs fichiers).

Exemple:

File3.js

var f3obj = "file3";

// Define other stuff

File2.js:

var f2obj = "file2";
$.getScript("file3.js", function(){

    alert(f3obj);

    // Use anything defined in file3.
});

File1.js:

$.getScript("file2.js", function(){
    alert(f3obj); //This will probably fail because file3 is only guaranteed to have loaded inside the callback in file2.
    alert(f2obj);

    // Use anything defined in the loaded script...
});

Vous avez raison lorsque vous dites que vous pouvez spécifier Ajax pour s’exécuter de manière synchrone ou utiliser XMLHttpRequest, mais le la tendance actuelle semble être de déconseiller les demandes synchrones, de sorte que vous ne pouvez pas obtenir une prise en charge complète du navigateur maintenant ou à l'avenir.

Vous pouvez essayer d'utiliser $.when pour vérifier un tableau d'objets différés, mais maintenant vous le faites dans chaque fichier et le fichier2 sera considéré comme chargé dès que $.when sera exécuté, pas lorsque le rappel sera exécuté , donc file1 continue son exécution avant le chargement de file3. Cela a vraiment toujours le même problème.

J'ai décidé de reculer au lieu d'avancer. Merci document.writeln. Je sais que c'est tabou, mais tant qu'il est utilisé correctement, cela fonctionne bien. Vous vous retrouvez avec du code qui peut être débogué facilement, s'affiche correctement dans le DOM et peut garantir l'ordre de chargement correct des dépendances.

Vous pouvez bien sûr utiliser $ ("body"). Append (), mais vous ne pourrez plus déboguer correctement.

REMARQUE: vous ne devez l'utiliser que pendant le chargement de la page, sinon vous obtenez un écran vide. En d'autres termes, placez toujours ces informations avant / à l'extérieur du document. . Je n'ai pas testé l'utilisation de ceci après le chargement de la page dans un événement de clic ou quelque chose comme ça, mais je suis presque sûr que cela échouera.

J'ai aimé l'idée d'étendre jQuery, mais évidemment vous n'en avez pas besoin.

Avant d'appeler document.writeln, il vérifie que le script n'a pas déjà été chargé en évaluant tous les éléments du script.

Je suppose qu'un script n'est pas entièrement exécuté tant que son événement document.ready n'a pas été exécuté. (Je sais que l'utilisation de document.ready n'est pas requise, mais beaucoup de gens l'utilisent, et la manipulation est une sauvegarde.)

Lorsque les fichiers supplémentaires sont chargés, les rappels document.ready seront exécutés dans le mauvais ordre. Pour résoudre ce problème lorsqu'un script est réellement chargé, le script qui l'a importé est lui-même réimporté et l'exécution arrêtée. Ainsi, le fichier d'origine a désormais son rappel document.ready exécuté après l'un des scripts importés.

Au lieu de cette approche, vous pouvez essayer de modifier la jQuery readyList, mais cela semble être une pire solution.

Solution:

$.extend(true,
{
    import_js : function(scriptpath, reAddLast)
    {
        if (typeof reAddLast === "undefined" || reAddLast === null)
        {
            reAddLast = true; // Default this value to true. It is not used by the end user, only to facilitate recursion correctly.
        }

        var found = false;
        if (reAddLast == true) // If we are re-adding the originating script we do not care if it has already been added.
        {
            found = $('script').filter(function () {
                return ($(this).attr('src') == scriptpath);
            }).length != 0; // jQuery to check if the script already exists. (replace it with straight JavaScript if you don't like jQuery.
        }

        if (found == false) {

            var callingScriptPath = $('script').last().attr("src"); // Get the script that is currently loading. Again this creates a limitation where this should not be used in a button, and only before document.ready.

            document.writeln("<script type='text/javascript' src='" + scriptpath + "'></script>"); // Add the script to the document using writeln

            if (reAddLast)
            {
                $.import_js(callingScriptPath, false); // Call itself with the originating script to fix the order.
                throw 'Readding script to correct order: ' + scriptpath + ' < ' + callingScriptPath; // This halts execution of the originating script since it is getting reloaded. If you put a try / catch around the call to $.import_js you results will vary.
            }
            return true;
        }
        return false;
    }
});

Usage:

Fichier3:

var f3obj = "file3";

// Define other stuff
$(function(){
    f3obj = "file3docready";
});

Fichier2:

$.import_js('js/file3.js');
var f2obj = "file2";
$(function(){
    f2obj = "file2docready";
});

Fichier1:

$.import_js('js/file2.js');

// Use objects from file2 or file3
alert(f3obj); // "file3"
alert(f2obj); // "file2"

$(function(){
    // Use objects from file2 or file3 some more.
    alert(f3obj); //"file3docready"
    alert(f2obj); //"file2docready"
});
10
K.Dᴀᴠɪs 30 mars 2018 à 21:22

Je suis venu à cette question parce que je cherchais un moyen simple de maintenir une collection de plugins JavaScript utiles. Après avoir vu certaines des solutions ici, j'ai trouvé ceci:

  1. Configurez un fichier appelé "plugins.js" (ou extensions.js ou tout ce que vous voulez). Conservez vos fichiers de plugin avec ce seul fichier maître.

  2. plugins.js aura un tableau appelé pluginNames[] que nous allons parcourir sur each(), puis ajoutez une balise <script> à la tête de chaque plugin

//set array to be updated when we add or remove plugin files
var pluginNames = ["lettering", "fittext", "butterjam", etc.];

//one script tag for each plugin
$.each(pluginNames, function(){
    $('head').append('<script src="js/plugins/' + this + '.js"></script>');
});
  1. Appelez manuellement un seul fichier dans votre tête:
    <script src="js/plugins/plugins.js"></script>

MAIS:

Même si tous les plugins sont déposés dans la balise head comme ils le devraient, ils ne sont pas toujours exécutés par le navigateur lorsque vous cliquez sur la page ou actualisez.

J'ai trouvé qu'il est plus fiable d'écrire simplement les balises de script dans une inclusion PHP. Vous n'avez qu'à l'écrire une fois et c'est tout autant de travail que d'appeler le plugin en utilisant JavaScript.

9
rgb_life 10 janv. 2020 à 05:03

L'instruction import est en ECMAScript 6.

Syntaxe

import name from "module-name";
import { member } from "module-name";
import { member as alias } from "module-name";
import { member1 , member2 } from "module-name";
import { member1 , member2 as alias2 , [...] } from "module-name";
import name , { member [ , [...] ] } from "module-name";
import "module-name" as name;
73
Peter Mortensen 11 déc. 2016 à 09:47

Bien que ces réponses soient excellentes, il existe une "solution" simple qui existe depuis le chargement du script, et elle couvrira 99,999% des cas d'utilisation de la plupart des gens. Incluez simplement le script dont vous avez besoin avant le script qui l'exige. Pour la plupart des projets, il ne faut pas longtemps pour déterminer quels scripts sont nécessaires et dans quel ordre.

<!DOCTYPE HTML>
<html>
    <head>
        <script src="script1.js"></script>
        <script src="script2.js"></script>
    </head>
    <body></body>
</html>

Si script2 nécessite script1, c'est vraiment le moyen le plus simple de faire quelque chose comme ça. Je suis très surpris que personne n'ait soulevé cette question, car c'est la réponse la plus évidente et la plus simple qui s'appliquera dans presque tous les cas.

12
KthProg 12 avril 2018 à 19:38

La syntaxe @import pour réaliser une importation JavaScript de type CSS est possible en utilisant un outil tel que Mixture via leur type de fichier spécial .mix (voir ici). J'imagine que l'application utilise simplement l'une des méthodes susmentionnées en interne, bien que je ne sache pas.

Dans la documentation Mixture sur les fichiers .mix:

Les fichiers de mixage sont simplement des fichiers .js ou .css avec .mix. dans le nom du fichier. Un fichier de mixage étend simplement les fonctionnalités d'un fichier de style ou de script normal et vous permet d'importer et de combiner.

Voici un exemple de fichier .mix qui combine plusieurs fichiers .js en un seul:

// scripts-global.mix.js
// Plugins - Global

@import "global-plugins/headroom.js";
@import "global-plugins/retina-1.1.0.js";
@import "global-plugins/isotope.js";
@import "global-plugins/jquery.fitvids.js";

Le mélange affiche cela sous la forme scripts-global.js et également sous forme de version réduite (scripts-global.min.js).

Remarque: je ne suis en aucun cas affilié à Mixture, à part l'utiliser comme outil de développement frontal. Je suis tombé sur cette question en voyant un fichier .mix JavaScript en action (dans l'un des passe-partout Mixture) et en étant un peu confus ("vous pouvez le faire?", Je me suis dit). Ensuite, j'ai réalisé qu'il s'agissait d'un type de fichier spécifique à l'application (quelque peu décevant, d'accord). Néanmoins, a pensé que les connaissances pourraient être utiles pour les autres.

MISE À JOUR : le mélange est désormais gratuit (hors ligne).

MISE À JOUR : le mélange est désormais interrompu. Les anciennes versions de mélange sont toujours disponibles

14
ecv 17 déc. 2017 à 11:53

Il est possible de générer dynamiquement une balise JavaScript et de l'ajouter au document HTML à partir d'un autre code JavaScript. Cela chargera le fichier JavaScript ciblé.

function includeJs(jsFilePath) {
    var js = document.createElement("script");

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

    document.body.appendChild(js);
}

includeJs("/path/to/some/file.js");
94
Peter Mortensen 28 sept. 2013 à 12:44

Vous pouvez peut-être utiliser cette fonction que j'ai trouvée sur cette page Comment inclure un JavaScript fichier dans un fichier JavaScript? :

function include(filename)
{
    var head = document.getElementsByTagName('head')[0];

    var script = document.createElement('script');
    script.src = filename;
    script.type = 'text/javascript';

    head.appendChild(script)
}
60
Ajeet Lakhani 15 nov. 2014 à 17:01

Vous pouvez également assembler vos scripts en utilisant le PHP:

Fichier main.js.php:

<?php
    header('Content-type:text/javascript; charset=utf-8');
    include_once("foo.js.php");
    include_once("bar.js.php");
?>

// Main JavaScript code goes here
29
Peter Mortensen 28 sept. 2013 à 12:50

En langage moderne avec la vérification si le script a déjà été chargé ce serait:

function loadJs(url){
  return new Promise( (resolve, reject) => {
    if (document.querySelector(`head > script[src="${src}"]`) !== null) return resolve()
    const script = document.createElement("script")
    script.src = url
    script.onload = resolve
    script.onerror = reject
    document.head.appendChild(script)
  });
}

Utilisation (asynchrone / attente):

try { await loadJs("https://.../script.js") } 
catch(error) {console.log(error)}

Ou

await loadJs("https://.../script.js").catch(err => {})

Utilisation (promesse):

loadJs("https://.../script.js").then(res => {}).catch(err => {})
16
radulle 13 janv. 2020 à 07:50

La plupart des solutions présentées ici impliquent un chargement dynamique. Je cherchais à la place un compilateur qui assemble tous les fichiers dépendants en un seul fichier de sortie. Identique à Moins / Sass traitent la règle CSS @import. Comme je n'ai rien trouvé de convenable de ce genre, j'ai écrit un outil simple pour résoudre le problème.

Voici donc le compilateur, https://github.com/dsheiko/jsic, qui remplace $import("file-path") par le demandé le contenu du fichier en toute sécurité. Voici le plug-in Grunt correspondant: https: // github.com/dsheiko/grunt-jsic.

Sur la branche principale jQuery, ils concaténent simplement les fichiers source atomiques en un seul commençant par intro.js et se terminant par outtro.js. Cela ne me convient pas car il n'offre aucune flexibilité sur la conception du code source. Découvrez comment cela fonctionne avec jsic:

src / main.js

var foo = $import("./Form/Input/Tel");

src / Form / Input / Tel.js

function() {
    return {
          prop: "",
          method: function(){}
    }
}

Maintenant, nous pouvons exécuter le compilateur:

node jsic.js src/main.js build/mail.js

Et obtenez le fichier combiné

build / main.js

var foo = function() {
    return {
          prop: "",
          method: function(){}
    }
};
28
Peter Mortensen 19 oct. 2014 à 18:13

Je viens d'écrire ce code JavaScript (en utilisant Prototype pour DOM manipulation):

var require = (function() {
    var _required = {};
    return (function(url, callback) {
        if (typeof url == 'object') {
            // We've (hopefully) got an array: time to chain!
            if (url.length > 1) {
                // Load the nth file as soon as everything up to the
                // n-1th one is done.
                require(url.slice(0, url.length - 1), function() {
                    require(url[url.length - 1], callback);
                });
            } else if (url.length == 1) {
                require(url[0], callback);
            }
            return;
        }
        if (typeof _required[url] == 'undefined') {
            // Haven't loaded this URL yet; gogogo!
            _required[url] = [];

            var script = new Element('script', {
                src: url,
                type: 'text/javascript'
            });
            script.observe('load', function() {
                console.log("script " + url + " loaded.");
                _required[url].each(function(cb) {
                    cb.call(); // TODO: does this execute in the right context?
                });
                _required[url] = true;
            });

            $$('head')[0].insert(script);
        } else if (typeof _required[url] == 'boolean') {
            // We already loaded the thing, so go ahead.
            if (callback) {
                callback.call();
            }
            return;
        }

        if (callback) {
            _required[url].push(callback);
        }
    });
})();

Usage:

<script src="prototype.js"></script>
<script src="require.js"></script>
<script>
    require(['foo.js','bar.js'], function () {
        /* Use foo.js and bar.js here */
    });
</script>

Gist: http://gist.github.com/284442.

48
Talha Awan 25 juin 2017 à 21:04

Ma méthode habituelle est:

var require = function (src, cb) {
    cb = cb || function () {};

    var newScriptTag = document.createElement('script'),
        firstScriptTag = document.getElementsByTagName('script')[0];
    newScriptTag.src = src;
    newScriptTag.async = true;
    newScriptTag.onload = newScriptTag.onreadystatechange = function () {
        (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') && (cb());
    };
    firstScriptTag.parentNode.insertBefore(newScriptTag, firstScriptTag);
}

Cela fonctionne très bien et n'utilise aucun rechargement de page pour moi. J'ai essayé la méthode AJAX (l'une des autres réponses) mais cela ne semble pas fonctionner aussi bien pour moi.

Voici une explication du fonctionnement du code pour ceux qui sont curieux: essentiellement, il crée une nouvelle balise de script (après la première) de l'URL. Il le définit en mode asynchrone afin de ne pas bloquer le reste du code, mais appelle un rappel lorsque le readyState (l'état du contenu à charger) passe à «chargé».

13
Christopher Dumas 26 août 2017 à 17:02

Ce script ajoutera un fichier JavaScript en haut de toute autre balise <script>:

(function () {
    var li = document.createElement('script'); 
    li.type = 'text/javascript'; 
    li.src= "http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"; 
    li.async=true; 
    var s = document.getElementsByTagName('script')[0]; 
    s.parentNode.insertBefore(li, s);
})();
10
Peter Mortensen 19 oct. 2014 à 18:14

Il existe en fait est un moyen de charger un fichier JavaScript pas de manière asynchrone, vous pouvez donc utiliser les fonctions incluses dans votre fichier nouvellement chargé juste après le chargement, et je pense que cela fonctionne dans tous les navigateurs.

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

$("head").append('<script type="text/javascript" src="' + script + '"></script>');

Cependant, cette méthode a également un problème: si une erreur se produit dans le fichier JavaScript importé, Firebug (ainsi que Firefox Error Console et Chrome Developer Tools également) signaleront sa place de manière incorrecte, ce qui est un gros problème si vous utilisez Firebug pour suivre beaucoup les erreurs JavaScript (je le fais). Firebug ne connaît tout simplement pas le fichier nouvellement chargé pour une raison quelconque, donc si une erreur se produit dans ce fichier, il signale qu'elle s'est produite dans votre HTML, et vous aurez du mal à trouver la véritable raison de l'erreur.

Mais si cela ne vous pose pas de problème, 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 type="text/javascript" src="' + script + '"></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 fait un test simple pour cela à Exemple.

Il inclut un fichier main.js dans le HTML principal, puis le script dans 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 l'inclusion de included.js, la fonction hello() est appelée et vous obtenez l'alerte.

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

194
31piy 21 mars 2018 à 04:29