¿Cómo incluyo un archivo JavaScript en otro archivo JavaScript?

5195

¿Hay algo en JavaScript similar a @importCSS que le permita incluir un archivo JavaScript dentro de otro archivo JavaScript?

Alec Smart
fuente
82
@Daniel, no quiero usar una llamada AJAX.
Alec Smart
13
¿Por qué no declarar el archivo importado antes que el otro que lo requiere, simplemente usando scriptetiquetas ordenadas ?
falsarella
66
@Claudiu Eso no ayudaría a importar nada, pero también debería funcionar. Si tiene un archivo JS que depende de otro archivo JS, simplemente declare primero las etiquetas de script de los archivos de dependencia, de modo que el último ya tendrá cargadas sus dependencias. Si tiene una situación en la que no es un enfoque posible, las respuestas aquí deberían ser útiles.
falsarella
1
¿Cuál es la ventaja práctica de hacer esto? de cualquier manera, la base del código que depende del archivo javascript no se cargará y comenzará a funcionar en cualquier caso, ¡no se carga!
Ciasto piekarz

Respuestas:

4473

Las versiones anteriores de JavaScript no tenían importancia para importar, incluir o requerir, por lo que se han desarrollado muchos enfoques diferentes para este problema.

Pero desde 2015 (ES6), JavaScript ha tenido el estándar de módulos ES6 para importar módulos en Node.js, que también es compatible con la mayoría de los navegadores modernos .

Para compatibilidad con navegadores más antiguos, puede usar herramientas de compilación como Webpack y Rollup y / o herramientas de transpilación como Babel .

Módulos ES6

Los módulos ECMAScript (ES6) se han admitido en Node.js desde v8.5, con el --experimental-modulesindicador, y desde al menos Node.js v13.8.0 sin el indicador. Para habilitar "ESM" (vs sistema de módulos de estilo CommonJS anterior de Node.js [ "CJS"]) que sea para uso "type": "module"en package.jsono dar los archivos de la extensión .mjs. (Del mismo modo, los módulos escritos con el módulo CJS anterior de Node.js se pueden nombrar .cjssi su valor predeterminado es ESM).

Utilizando package.json:

{
    "type": "module"
}

Entonces module.js:

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

Entonces main.js:

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

Usando .mjs, tendrías module.mjs:

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

Entonces main.mjs:

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

Módulos ECMAScript en navegadores

Los navegadores han tenido soporte para cargar módulos ECMAScript directamente (no se requieren herramientas como Webpack) desde Safari 10.1, Chrome 61, Firefox 60 y Edge 16. Verifique el soporte actual en caniuse . No hay necesidad de usar la .mjsextensión Node.js ; los navegadores ignoran por completo las extensiones de archivo en módulos / 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);
}

Lea más en https://jakearchibald.com/2017/es-modules-in-browsers/

Importaciones dinámicas en navegadores

Las importaciones dinámicas permiten que el script cargue otros scripts según sea necesario:

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

Obtenga más información en https://developers.google.com/web/updates/2017/11/dynamic-import

Node.js requiere

El estilo de módulo CJS anterior, que todavía se usa ampliamente en Node.js, es el module.exports/require system.

// mymodule.js
module.exports = {
   hello: function() {
      return "Hello";
   }
}
// server.js
const myModule = require('./mymodule');
let val = myModule.hello(); // val is "Hello"   

Hay otras formas para que JavaScript incluya contenido externo de JavaScript en navegadores que no requieren preprocesamiento.

Carga AJAX

Puede cargar un script adicional con una llamada AJAX y luego usarlo evalpara ejecutarlo. Esta es la forma más sencilla, pero está limitada a su dominio debido al modelo de seguridad de sandbox de JavaScript. El uso evaltambién abre la puerta a errores, hacks y problemas de seguridad.

Recuperar carga

Al igual que Dynamic Imports, puede cargar uno o varios scripts con una fetchllamada usando promesas para controlar el orden de ejecución de las dependencias de script usando la biblioteca Fetch Inject :

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

jQuery Loading

La biblioteca jQuery proporciona funcionalidad de carga en una línea :

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

Carga dinámica de guiones

Puede agregar una etiqueta de script con la URL del script en el HTML. Para evitar la sobrecarga de jQuery, esta es una solución ideal.

El script incluso puede residir en un servidor diferente. Además, el navegador evalúa el código. La <script>etiqueta puede inyectarse en la página web <head>o insertarse justo antes de la </body>etiqueta de cierre .

Aquí hay un ejemplo de cómo esto podría funcionar:

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)
}

Esta función agregará una nueva <script>etiqueta al final de la sección de encabezado de la página, donde el srcatributo se establece en la URL que se le asigna a la función como primer parámetro.

Ambas soluciones se analizan e ilustran en JavaScript Madness: Dynamic Script Loading .

Detectando cuando el script ha sido ejecutado

Ahora, hay un gran problema que debes conocer. Hacer eso implica que cargue el código de forma remota . Los navegadores web modernos cargarán el archivo y seguirán ejecutando su script actual porque cargan todo de forma asíncrona para mejorar el rendimiento. (Esto se aplica tanto al método jQuery como al método de carga de script dinámico manual).

Significa que si usa estos trucos directamente, no podrá usar su código recién cargado en la siguiente línea después de solicitar que se cargue , porque todavía se cargará.

Por ejemplo: my_lovely_script.jscontiene 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

Luego vuelves a cargar la página golpeando F5. ¡Y funciona! Confuso...

Entonces, ¿qué hacer al respecto?

Bueno, puedes usar el truco que sugiere el autor en el enlace que te di. En resumen, para las personas apuradas, usa un evento para ejecutar una función de devolución de llamada cuando se carga el script. Entonces puede poner todo el código usando la biblioteca remota en la función de devolución de llamada. Por ejemplo:

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);
}

Luego escribe el código que desea usar DESPUÉS de que el script se carga en una función lambda :

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

Entonces ejecutas todo eso:

loadScript("my_lovely_script.js", myPrettyCode);

Tenga en cuenta que el script puede ejecutarse después de que se haya cargado el DOM, o antes, según el navegador y si incluyó la línea script.async = false;. Hay un gran artículo sobre la carga de Javascript en general que analiza esto.

Código fuente de fusión / preprocesamiento

Como se menciona en la parte superior de esta respuesta, muchos desarrolladores usan herramientas de compilación / transpilación como Parcel, Webpack o Babel en sus proyectos, lo que les permite usar la próxima sintaxis de JavaScript, proporcionar compatibilidad con versiones anteriores de navegadores antiguos, combinar archivos, minimizar, realizar división de código, etc.

e-satis
fuente
131
No, pero alguien que usa algo tan avanzado como Rhino o no haría esta pregunta.
e-satis
193
Para completar, hay una tercera forma: en ciertas soluciones, cuando controlas ambos archivos javascript, puedes crear 1 archivo javascript gigante que combina el contenido de ambos archivos.
Sapo
20
No debería "document.createElement (" my_lovely_script.js ");" en el ejemplo ser "document.createElement (" script ")"?
Russell Silva
14
¿Cómo eval abre la puerta a los hacks si es el código que está ejecutando?
Vince Panuccio
66
Su respuesta requiere alguna modificación para IE ( onreadystatechangeevento y readyStatepropiedad). Además, la carga de scripts dinámicos no se beneficia de los escáneres de precarga del broswer. Recomiende este artículo HTML5Rocks: html5rocks.com/en/tutorials/speed/script-loading
ruhong
571

Si alguien está buscando algo más avanzado, pruebe RequireJS . Obtendrá beneficios adicionales como la administración de dependencias, una mejor concurrencia y evitará la duplicación (es decir, recuperar un script más de una vez).

Puede escribir sus archivos JavaScript en "módulos" y luego hacer referencia a ellos como dependencias en otros scripts. O puede usar RequireJS como una solución simple "vaya a buscar este script".

Ejemplo:

Definir dependencias como módulos:

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
});

implement.js es su archivo JavaScript "principal" que depende de some-dependency.js

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

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

Extracto del archivo README de GitHub :

RequireJS carga archivos JavaScript simples así como módulos más definidos. Está optimizado para su uso en el navegador, incluso en un Web Worker, pero se puede usar en otros entornos JavaScript, como Rhino y Node. Implementa la API del módulo asíncrono.

RequireJS utiliza etiquetas de script simples para cargar módulos / archivos, por lo que debería permitir una depuración fácil. Se puede usar simplemente para cargar archivos JavaScript existentes, por lo que puede agregarlo a su proyecto existente sin tener que volver a escribir sus archivos JavaScript.

...

John Strickler
fuente
1
@aaaidan: la razón de MattDmo además se basa en una biblioteca externa que a cambio depende de la respuesta aceptada.
David Mulder
1
Para superar require.js, lo último sería js angular, que es más estable y fácil de usar, junto con otras funciones HTML vinculantes y ricas.
zeeshan
55
-1: Esas abstracciones - "alguna_dependencia" - son realmente pobres, con índices que aumentan la confusión. Me cuesta entender cómo se ve un ejemplo de código de trabajo. Si el autor proporcionara un ejemplo de trabajo, casi cualquiera podría adaptarlo y generalizarlo según sus necesidades.
Tegiri Nenashi
1
no funciona bien con MVC y la agrupación de scripts con
minificación
1
'agregar ... sin tener que volver a escribir sus archivos JavaScript'; genial, pero ¿cómo exactamente? Canalla. la respuesta sugiere agregar un 'require' (no 'requirejs'?) al script principal + un 'define' a cada archivo dependiente, ¿sí? Pero eso ES reescribir, ¿qué es lo que no se reescribe? -resto de código ya que RequireJS permite que un archivo haga defs globales de manera normal? -¿lo hace? Acabo de intentar eso, + (¿olvidado?) <Script src = " requirejs.org/docs/release/2.2.0/comments/require.js "> </script>, luego 'requirejs ([' GoogleDrive.com/host /..',..font>,function(a,b) {mycode}) ': Firebug dice que cada dependiente cargado PERO sus defs no están definidas en mycode y después.
Destiny Architect
196

En realidad, hay una manera de cargar un archivo JavaScript no asincrónicamente, por lo que podría usar las funciones incluidas en su archivo recién cargado justo después de cargarlo, y creo que funciona en todos los navegadores.

Debe usar jQuery.append()el <head>elemento de su página, es decir:

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

Sin embargo, este método también tiene un problema: si ocurre un error en el archivo JavaScript importado, Firebug (y también Firefox Error Console y Chrome Developer Tools también) informarán su lugar incorrectamente, lo cual es un gran problema si usa Firebug para rastrear Los errores de JavaScript bajan mucho (lo hago). Firebug simplemente no conoce el archivo recién cargado por algún motivo, por lo que si se produce un error en ese archivo, informa que se produjo en su archivo HTML principal y tendrá problemas para descubrir el motivo real del error.

Pero si eso no es un problema para usted, entonces este método debería funcionar.

De hecho, he escrito un complemento jQuery llamado $ .import_js () que usa este método:

(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);

Entonces, todo lo que necesitaría hacer para importar JavaScript es:

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

También hice una prueba simple para esto en Example .

Incluye un main.jsarchivo en el HTML principal y luego el script se main.jsusa $.import_js()para importar un archivo adicional llamado included.js, que define esta función:

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

Y justo después de incluir included.js, hello()se llama a la función y obtienes la alerta.

(Esta respuesta es en respuesta al comentario de e-satis).

Kipras
fuente
Estoy probando este método, pero no funciona para mí, el elemento simplemente no aparece en la etiqueta de la cabeza.
sitios
16
@juanpastas - úsala jQuery.getScript, así no tienes que preocuparte por escribir el complemento ...
MattDMo
66
Hmm, según este artículo , agregar un scriptelemento headhará que se ejecute de forma asíncrona, a menos que asyncse establezca específicamente en false.
Flimm
1
¿No debería la variable de script tener entidades html codificadas? Si el enlace contiene el "código, se romperá
RedClover
1
@Flimm querido señor, mi equipo y yo agradecemos su comentario y personalmente le debo una cerveza de dinero si alguna vez nos encontramos en persona
Alex
155

Otra forma, que en mi opinión es mucho más limpia, es hacer una solicitud Ajax sincrónica en lugar de usar una <script>etiqueta. Que también es cómo incluye Node.js.

Aquí hay un ejemplo usando 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);
        }
    });
}

Luego puede usarlo en su código, ya que generalmente usaría un include:

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

Y poder llamar a una función desde el script requerido en la siguiente línea:

subscript.doSomethingCool(); 
Ariel
fuente
1
Buena solución, el cabezal incluido es asíncrono, desafortunadamente, la solución ajax funciona
Matteo Conta
17
Como alguien más mencionó, requirejs.org hace esto y también tiene un precompilador que reúne los archivos js para que se carguen más rápido. Es posible que desee verlo.
Ariel
2
Descubrí que podía depurarlo agregando esta directiva al final del archivo para Chrome: // @ sourceURL = view_index.js
Todd Vance
11
desafortunadamente, async: false ahora está en desuso en jQuery. Podría romperse en el futuro, así que lo evitaría.
sqram
3
@katsh No estamos usando objetos jqXHR aquí. Su cotización no parece respaldar su comentario anterior indicando que async: falsesupuestamente está en desuso. ¡No lo es! Como dice su cita, solo lo relacionado con jqXHR es.
Zero3
101

Hay una buena noticia para ti. Muy pronto podrá cargar el código JavaScript fácilmente. Se convertirá en una forma estándar de importar módulos de código JavaScript y formará parte del núcleo de JavaScript.

Simplemente tiene que escribir import cond from 'cond.js';para cargar una macro nombrada conddesde un archivo cond.js.

Por lo tanto, no tiene que confiar en ningún marco de JavaScript ni debe hacer explícitamente llamadas Ajax .

Referirse a:

Soy papá
fuente
12
require / import en jsfile ha sido demasiado tiempo en el futuro. (OMI)
rwheadon
66
¡@rwheadon sí parece terrible que esto no sea parte del lenguaje! ¡Cómo la gente hace algo está más allá de mí! Soy nuevo en esto y esto parece ser el peor (de muchos) trozos de locura
JonnyRaa
@ jonny-leeds Incluso sin la carga de módulos incorporada, JavaScript en el navegador es lo suficientemente flexible como para que podamos implementar una biblioteca como RequireJS para la gestión de nuestro módulo.
Keen
8
mediados de 2015- Todavía no se implementó en ningún navegador, developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
scape
si, tienes razón. ahora estoy empezando a sentirme mal por esto :(. Thouh, una vez implementado en todos los navegadores, esta será una gran característica integrada en JavaScript.
Imdad
97

Es posible generar dinámicamente una etiqueta JavaScript y agregarla al documento HTML desde otro código JavaScript. Esto cargará el archivo JavaScript dirigido.

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");
Svitlana Maksymchuk
fuente
8
@ e-satis: en realidad, esta es una ventaja, un script de sincronización estaría bloqueando. Caballos para los cursos, pero 9 de cada 10 veces desea la opción sin bloqueo.
annakata
@Svitlana: los elementos de script creados de esta manera son asíncronos. Actualmente, esto podría verse como explotar una escapatoria, por lo que podría no ser una prueba futura, no he visto nada en ningún estándar que aclare esto.
annakata
En realidad, lo retiro, me di cuenta de que estás apegando al cuerpo en lugar de a la cabeza.
annakata
@annakata: ¿Cuál es la diferencia? Por cierto, yahoo sugiere agregar etiquetas de script al final del cuerpo, por lo que no debería haber nada de malo al agregar dinámicamente.
Svitlana Maksymchuk
77
@ e-satis asynchronous es bueno porque no congelará tu página. Utilice la devolución de llamada para recibir una notificación cuando js.onload = callback;
termine
74

La declaración importestá en ECMAScript 6.

Sintaxis

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;
draupnie
fuente
... pero no es compatible con ningún navegador hasta la fecha, de acuerdo con la tabla de compatibilidad en la página a la que se vinculó.
Zero3
66
Ahora puede escribir código ES6 y compilarlo con Babel.js ( babeljs.io ) en cualquier sistema de módulo actual que prefiera (CommonJS / AMD / UMD): babeljs.io/docs/usage/modules
Jeremy Harris
@ Zero3 Aparentemente, el nuevo IE (Edge) es el único
Julian Avar el
en 2019, IE todavía no admite esto de ninguna forma. ¿Por qué Microsoft debe estar tan en contra de la usabilidad?
GreySage
61

Quizás pueda usar esta función que encontré en esta página ¿Cómo incluyo un archivo JavaScript en un archivo 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)
}
Arnaud Gouder de Beauregard
fuente
55
Debería ser útil agregarscript.onload = callback;
Vitim.us
@SvitlanaMaksymchuk entonces, si no uso var, ¿la variable será global?
Francisco Corrales Morales
@FranciscoCorrales sí.
Christopher Chiche
Termina en global con o sin la var :)
Vedran Maricevic.
Esto falla si la página no tienehead .
Dan Dascalescu
54

Aquí hay una versión sincrónica sin 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);
}

Tenga en cuenta que para que este dominio cruzado funcione, el servidor deberá establecer el allow-originencabezado en su respuesta.

heinob
fuente
Excelente funcion! Carga el JavaScript antes de que cualquier JS adicional se escriba después del cuerpo. Muy importante al cargar múltiples scripts.
tfont
3
@heinob: ¿Qué puedo hacer para que funcione para dominios cruzados? (cargando script desde http://web.archive.org/web/20140905044059/http://www.howtocreate.co.uk/operaStuff/userjs/aagmfunctions.js)
user2284570
@ user2284570: Si es el propietario del dominio externo: establezca el encabezado `allow-origin 'en la respuesta del servidor. Si no eres el dueño: nada. ¡Lo siento! Esa es la política de origen cruzado.
heinob
2
@ user2284570: entiendo tu comentario de esa manera, que no eres el propietario del dominio desde el que quieres cargar el script. En ese caso, solo puede cargar un script a través de una <script>etiqueta insertada , no a través de XMLHttpRequest.
heinob
2
Para aquellos que planean usar esto en Firefox (digamos para las secuencias de comandos de imacros), agregue esta línea en la parte superior del archivo:const XMLHttpRequest = Components.Constructor("@mozilla.org/xmlextras/xmlhttprequest;1");
Kwestion
49

Acabo de escribir este código JavaScript (usando Prototype para la manipulación DOM ):

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);
        }
    });
})();

Uso:

<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 .

nornagon
fuente
77
jrburke escribió esto como RequireJS. Github: requirejs.org/docs/requirements.html
Mike Caron
¿No está poniendo el script cargado fuera del alcance donde se llama a require ()? Parece que eval () es la única forma de hacerlo dentro del alcance. ¿O hay otra manera?
trusktr
44

Aquí está la versión generalizada de cómo Facebook lo hace por su ubicuo botón Me gusta:

<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 funciona para Facebook, funcionará para usted.

La razón por la que buscamos el primer scriptelemento en lugar de heado bodyes porque algunos navegadores no crean uno si faltan, pero estamos garantizados de tener un scriptelemento: este. Lea más en http://www.jspatterns.com/the-ridiculous-case-of-adding-a-script-element/ .

Dan Dascalescu
fuente
3
¡Muy bien! Algunos de los métodos aquí también funcionan, pero en una configuración dinámica, esto funciona mejor.
tfont
extendí tu script para eliminar la duplicación
Kamil Dąbrowski
39

Si quieres en JavaScript puro, puedes usarlo document.write.

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

Si usa la biblioteca jQuery, puede usar el $.getScriptmétodo.

$.getScript("another_script.js");
Venu immadi
fuente
8
¿document.write eliminaría todo lo demás?
Eisa Adil
30

También puedes ensamblar tus scripts usando PHP :

Archivo 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
Calmarius
fuente
16
Parece que el punto es mantener todo esto en javascript en la parte delantera
Ariel
1
Gracias por recordar esto. También puede hacer que PHP escriba etiquetas <script> en su encabezado HTML, para que se carguen los archivos js que necesita (y solo esos).
Rolf
29

La mayoría de las soluciones que se muestran aquí implican una carga dinámica. Estaba buscando un compilador que reúne todos los archivos dependientes en un solo archivo de salida. Lo mismo que los preprocesadores Less / Sass tratan con la @importregla at CSS . Como no encontré nada decente de este tipo, escribí una herramienta simple para resolver el problema.

Así que aquí está el compilador, https://github.com/dsheiko/jsic , que reemplaza $import("file-path")con seguridad el contenido del archivo solicitado. Aquí está el complemento Grunt correspondiente : https://github.com/dsheiko/grunt-jsic .

En la rama maestra jQuery, simplemente concatenan los archivos de origen atómico en uno solo que comienza intro.jsy termina con outtro.js. Eso no me conviene, ya que no proporciona flexibilidad en el diseño del código fuente. Mira cómo funciona con jsic:

src / main.js

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

src / Form / Input / Tel.js

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

Ahora podemos ejecutar el compilador:

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

Y obtener el archivo combinado

build / main.js

var foo = function() {
    return {
          prop: "",
          method: function(){}
    }
};
Dmitry Sheiko
fuente
2
Desde esta publicación se me ocurrió una solución mucho mejor: compilador de módulos CommonJS: github.com/dsheiko/cjsc Para que pueda simplemente escribir módulos CommonJs o NodeJs y acceder entre sí, manteniéndolos en ámbitos aislados. Los beneficios: no necesita múltiples solicitudes HTTP que afecten el rendimiento. No necesita envolver manualmente el código de su módulo; es responsabilidad del compilador (por lo tanto, mejor legibilidad del código fuente). No necesita ninguna biblioteca externa. Es compatible con UMD- y módulos NodeJs (por ejemplo, puede abordar jQuery, Backbone como módulos sin tocar su código)
Dmitry Sheiko
26

Si su intención de cargar el archivo JavaScript está utilizando las funciones del archivo importado / incluido , también puede definir un objeto global y establecer las funciones como elementos de objeto. Por ejemplo:

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();

Solo debe tener cuidado cuando incluya scripts en un archivo HTML. El orden debe ser el siguiente:

<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>
Adem Ilhan
fuente
22

Esto debería hacer:

xhr = new XMLHttpRequest();
xhr.open("GET", "/soap/ajax/11.0/connection.js", false);
xhr.send();
eval(xhr.responseText);
tggagne
fuente
55
el evales lo que está mal con él. De Crockford , " evalque es malo. La evalfunción es la característica más mal uso de JavaScript. Evitarla. evalTiene alias. No utilice el Functionconstructor. No pase cuerdas a setTimeouto setInterval." Si no ha leído su "JavaScript: las partes buenas", salga y hágalo ahora mismo. No te arrepentirás.
MattDMo
13
@MattDMo "Alguien dijo que era malo" no es realmente una discusión.
Casey
44
@emodendroket Supongo que no sabes quién es Douglas Crockford .
MattDMo
13
@MattDMo Soy completamente consciente de quién es él, pero es un ser humano, no un dios.
Casey
2
@tggagne: ¿Qué puedo hacer para que funcione para dominios cruzados? (cargando script desde http://web.archive.org/web/20140905044059/http://www.howtocreate.co.uk/operaStuff/userjs/aagmfunctions.js)
user2284570
21

O, en lugar de incluir en tiempo de ejecución, use un script para concatenar antes de cargar.

Yo uso Sprockets (no sé si hay otros). Construye su código JavaScript en archivos separados e incluye comentarios procesados ​​por el motor Sprockets como incluye. Para el desarrollo, puede incluir archivos secuencialmente, luego, para la producción, fusionarlos ...

Ver también:

JMawer
fuente
Browserify es mucho más popular que Sprockets.
Dan Dascalescu
18

Tenía un problema simple, pero estaba desconcertado por las respuestas a esta pregunta.

Tuve que usar una variable (myVar1) definida en un archivo JavaScript (myvariables.js) en otro archivo JavaScript (main.js).

Para esto hice lo siguiente:

Cargó el código JavaScript en el archivo HTML, en el orden correcto, myvariables.js primero, luego main.js:

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

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

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

Archivo: myvariables.js

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

Archivo: main.js

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

Como viste, había usado una variable en un archivo JavaScript en otro archivo JavaScript, pero no necesitaba incluir uno en otro. Solo necesitaba asegurarme de que el primer archivo JavaScript se cargara antes que el segundo archivo JavaScript, y que las variables del primer archivo JavaScript estén accesibles en el segundo archivo JavaScript, automáticamente.

Esto me salvó el día. Espero que esto ayude.

Manohar Reddy Poreddy
fuente
El problema con esta respuesta es que no es algo así import. Necesita un archivo HTML para obtener cosas de un archivo js a otro.
Cannicidio
Muy cierto. Eso es lo que algunas otras respuestas tienen como soluciones. Sin embargo, tenía dos archivos JS, uno debería usar otras variables de JS. No node.js, next.js, express.js, etc., por lo que importar O requerir no funcionará, solo tenía archivos .js simples.
Manohar Reddy Poreddy
Sin embargo, es comprensible que la pregunta realmente sea importar un archivo javascript dentro de otro archivo, no solo acceder a sus variables usando un archivo HTML. Por ejemplo, suponga que está haciendo funcionalidad para un botón, y utiliza tres archivos js diferentes, uno para el manejo de clics, uno para el manejo de desplazamiento, uno para las devoluciones de llamada para cada uno de los otros dos. Sería útil importar los otros dos js en el tercer js mismo, y solo tener una <script>etiqueta. Esto puede ayudar con la organización. Esta respuesta simplemente no es lo que la pregunta estaba pidiendo, y no es ideal en este contexto.
Cannicidio
Cuando busqué la solución para mi problema, busqué de la manera correcta, sin embargo, Google cree que esta es la página correcta, así que llegué aquí. Por eso escribí mi respuesta aquí. Parece que hice lo correcto, debido a los 15 votos a favor mencionados arriba. Para no perder el tiempo de otras personas, he dejado claro cuál es mi escenario, he puesto el código HTML primero, lo que parece ayudado, ya que respondiste y dijiste que html no es tu escenario. Espero que eso se aclare.
Manohar Reddy Poreddy
Sí, de hecho parece que algunas personas buscaron un problema ligeramente diferente, para lo cual esta es una solución, y lo encontraron. Aunque esta no es necesariamente la respuesta a esta pregunta, definitivamente es la respuesta a otra pregunta similar. Como tal, está bien tener esta respuesta aquí, ya que ayuda a aquellos que estaban buscando esa respuesta. Gracias por esa respuesta, eso lo aclaró.
Cannicidio
16

En caso de que esté utilizando Web Workers y desee incluir scripts adicionales en el ámbito del trabajador, las otras respuestas proporcionaron sobre la adición de scripts ahead etiqueta, etc., no funcionarán para usted.

Afortunadamente, los Web Workers tienen su propia importScriptsfunción, que es una función global en el ámbito del Web Worker, nativa del navegador, ya que forma parte de la especificación .

Alternativamente, como destaca la segunda respuesta más votada a su pregunta , RequireJS también puede manejar la inclusión de scripts dentro de un Web Worker (probablemente llamándose a importScriptssí mismo, pero con algunas otras características útiles).

Turnerj
fuente
16

En lenguaje moderno con la comprobación de si el script ya se ha cargado, sería:

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)
  });
}

Uso (asíncrono / espera):

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

o

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

Uso (promesa):

loadJs("https://.../script.js").then(res => {}).catch(err => {})
Dmitry Sheiko
fuente
Agradable. Buena solución.
Naftali aka Neal
Conciso y solo necesita ES5, y elegantemente evita tener que devolver la llamada formalmente. Gracias Dmitry!
Eureka
Wow, funciona en el navegador sin servidor. pi.js = simplemente var pi = 3.14. llame a la función loadJS () a través deloadJs("pi.js").then(function(){ console.log(pi); });
zipzit
14

La @importsintaxis para lograr la importación de JavaScript similar a CSS es posible utilizando una herramienta como Mixture a través de su .mixtipo de archivo especial (consulte aquí ). Me imagino que la aplicación simplemente usa uno de los métodos antes mencionados de forma interna, aunque no lo sé.

De la documentación de la Mezcla en los .mixarchivos:

Los archivos de mezcla son simplemente archivos .js o .css con .mix. en el nombre del archivo. Un archivo de mezcla simplemente extiende la funcionalidad de un archivo de estilo o script normal y le permite importar y combinar.

Aquí hay un .mixarchivo de ejemplo que combina varios .jsarchivos en uno:

// 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";

Mixture genera esto como scripts-global.jsy también como una versión minimizada (scripts-global.min.js ).

Nota: de ninguna manera estoy afiliado a Mixture, aparte de usarlo como una herramienta de desarrollo front-end. Encontré esta pregunta al ver un .mixarchivo JavaScript en acción (en una de las repeticiones de Mixture) y estar un poco confundido ("¿puedes hacer esto?", Pensé para mí). Luego me di cuenta de que era un tipo de archivo específico de la aplicación (algo decepcionante, de acuerdo). Sin embargo, pensé que el conocimiento podría ser útil para otros.

ACTUALIZACIÓN : La mezcla ahora es gratuita (sin conexión).

ACTUALIZACIÓN : La mezcla ahora se descontinúa. Los lanzamientos de mezclas antiguas todavía están disponibles

Isaac Gregson
fuente
Esto sería increíble si fuera un módulo de nodo.
b01
@ b01 Suena como un desafío;) Si solo tuviera el tiempo ... ¿tal vez alguien más lo haga?
Isaac Gregson el
13

Mi método habitual es:

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);
}

Funciona muy bien y no utiliza recargas de página para mí. He probado el método AJAX (una de las otras respuestas) pero no parece funcionar tan bien para mí.

Aquí hay una explicación de cómo funciona el código para aquellos que son curiosos: esencialmente, crea una nueva etiqueta de script (después de la primera) de la URL. Lo establece en modo asíncrono para que no bloquee el resto del código, pero llama a una devolución de llamada cuando readyState (el estado del contenido que se va a cargar) cambia a 'cargado'.

Christopher Dumas
fuente
13

Aunque estas respuestas son excelentes, existe una "solución" simple que existe desde que existió la carga de scripts, y cubrirá el 99.999% de los casos de uso de la mayoría de las personas. Simplemente incluya el script que necesita antes del script que lo requiere. Para la mayoría de los proyectos, no lleva mucho tiempo determinar qué scripts son necesarios y en qué orden.

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

Si script2 requiere script1, esta es realmente la forma más fácil de hacer algo como esto. Estoy muy sorprendido de que nadie haya mencionado esto, ya que es la respuesta más obvia y más simple que se aplicará en casi todos los casos.

KthProg
fuente
1
Supongo que para muchas personas, incluido yo mismo, necesitamos un nombre de archivo dinámico.
Stuart McIntyre
1
@StuartMcIntyre en ese caso, establezca el atributo src de la etiqueta del script en tiempo de ejecución y espere el evento de carga (por supuesto, hay mejores soluciones en ese caso en 2019).
KthProg
12

Escribí un módulo simple que automatiza el trabajo de importar / incluir scripts de módulos en JavaScript. Para obtener una explicación detallada del código, consulte la publicación del blog JavaScript require / import / include 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);
};
stamat
fuente
10

Este script agregará un archivo JavaScript en la parte superior de cualquier otra <script>etiqueta:

(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);
})();
Vicky Gonsalves
fuente
10

También hay Head.js . Es muy fácil tratar con:

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

Como puede ver, es más fácil que Require.js y tan conveniente como el $.getScriptmétodo de jQuery . También tiene algunas funciones avanzadas, como carga condicional, detección de funciones y mucho más .

Cerveza inglesa
fuente
10

Hay muchas respuestas potenciales para esta pregunta. Mi respuesta obviamente se basa en varios de ellos. Esto es lo que terminé después de leer todas las respuestas.

El problema $.getScripty cualquier otra solución que requiera una devolución de llamada cuando se complete la carga es que si tiene varios archivos que lo usan y dependen el uno del otro, ya no tiene una manera de saber cuándo se han cargado todos los scripts (una vez que están anidados) en múltiples archivos).

Ejemplo:

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

Tiene razón cuando dice que podría especificar que Ajax se ejecute sincrónicamente o usar XMLHttpRequest , pero parece que la tendencia actual es desaprobar las solicitudes sincrónicas, por lo que es posible que no obtenga soporte completo del navegador ahora o en el futuro.

Puede intentar usar $.whenpara verificar una matriz de objetos diferidos, pero ahora lo está haciendo en cada archivo y el archivo2 se considerará cargado tan pronto como $.whense ejecute, no cuando se ejecute la devolución de llamada, por lo que el archivo1 aún continúa la ejecución antes de cargar el archivo3 . Esto realmente todavía tiene el mismo problema.

Decidí ir hacia atrás en lugar de hacia adelante. Gracias document.writeln. Sé que es tabú, pero siempre que se use correctamente, esto funciona bien. Termina con un código que se puede depurar fácilmente, se muestra en el DOM correctamente y puede garantizar el orden en que las dependencias se cargan correctamente.

Por supuesto, puede usar $ ("body"). Append (), pero ya no puede depurar correctamente.

NOTA: debe usar esto solo mientras se carga la página; de lo contrario, aparecerá una pantalla en blanco. En otras palabras, siempre coloque esto antes / fuera de document.ready . No he probado usar esto después de que la página se carga en un evento de clic o algo así, pero estoy bastante seguro de que fallará.

Me gustó la idea de extender jQuery, pero obviamente no es necesario.

Antes de llamar document.writeln, verifica para asegurarse de que el script no se haya cargado ya evaluando todos los elementos del script.

Supongo que un script no se ejecuta completamente hasta document.readyque se haya ejecutado su evento. (Sé que el uso document.readyno es obligatorio, pero muchas personas lo usan, y manejar esto es una salvaguardia).

Cuando se cargan los archivos adicionales, las document.readydevoluciones de llamada se ejecutarán en el orden incorrecto. Para solucionar esto cuando un script se carga realmente, el script que lo importó se vuelve a importar y la ejecución se detiene. Esto hace que el archivo de origen ahora tenga su document.readydevolución de llamada ejecutada después de cualquiera de los scripts que importa.

En lugar de este enfoque, podría intentar modificar jQuery readyList, pero esto parecía una solución peor.

Solución:

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

Uso:

Archivo3:

var f3obj = "file3";

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

Archivo2:

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

Archivo1:

$.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"
});
genio de pelo rizado
fuente
Esto es exactamente lo que dice la respuesta actualmente aceptada: simplemente no es suficiente.
Cannicidio
La principal diferencia es que si falta una dependencia, agregará la etiqueta de script para la dependencia, luego también agregará la etiqueta de script para el archivo de llamada y arrojará un error que detiene la ejecución. Esto hace que los scripts se procesen y se ejecuten en el orden correcto y elimina la necesidad de devoluciones de llamada. Por lo tanto, el script dependiente se cargará y ejecutará antes del script de llamada mientras admite la anidación.
curlyhairedgenius
En cuanto a "la tendencia actual parece ser la de desaprobar las solicitudes síncronas", esto es cierto solo porque muchos desarrolladores las han usado mal y han hecho que los usuarios esperen innecesariamente. Sin embargo, si la solicitud es naturalmente síncrona, como una declaración de inclusión, entonces Ajax síncrono simple está bien. Creé una función de extensión de JavaScript general que ejecuta sincrónicamente funciones como leer un archivo que no es parte de JavaScript ejecutando un archivo "servidor" de PHP, y lo encuentro muy útil al escribir aplicaciones usando JavaScript. No se necesita un servidor web local para tal Ajax.
David Spector
10

Existen varias formas de implementar módulos en Javascript. Estas son las 2 más populares:

Módulos ES6

Los navegadores aún no admiten este sistema de modulación, por lo que para que pueda usar esta sintaxis, debe usar un paquete como webpack. Usar un paquete es mejor de todos modos porque puede combinar todos sus archivos diferentes en un solo archivo (o un par relacionado). Esto servirá los archivos del servidor al cliente más rápido porque cada solicitud HTTP tiene una sobrecarga asociada acompañada. Por lo tanto, al reducir la solicitud HTTP general, mejoramos el rendimiento. Aquí hay un ejemplo de módulos 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 (utilizado en NodeJS)

Este sistema de modulación se usa en NodeJS. Básicamente agrega sus exportaciones a un objeto que se llama module.exports. Luego puede acceder a este objeto a través de a require('modulePath'). Lo importante aquí es darse cuenta de que estos módulos se están almacenando en caché, por lo que si require()un determinado módulo dos veces devolverá el módulo ya creado.

// 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
Willem van der Veen
fuente
9

Llegué a esta pregunta porque estaba buscando una manera simple de mantener una colección de complementos útiles de JavaScript. Después de ver algunas de las soluciones aquí, se me ocurrió esto:

  1. Configure un archivo llamado "plugins.js" (o extensiones.js o lo que quiera). Mantenga sus archivos de complemento junto con ese archivo maestro.

  2. plugins.js tendrá una matriz llamada pluginNames[]que iteraremos each(), luego agregaremos una <script>etiqueta a la cabeza para cada complemento

//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. Llame manualmente solo un archivo en su cabeza:
    <script src="js/plugins/plugins.js"></script>

PERO:

A pesar de que todos los complementos se colocan en la etiqueta principal de la forma en que deberían hacerlo, el navegador no siempre los ejecuta cuando hace clic en la página o se actualiza.

He encontrado que es más confiable simplemente escribir las etiquetas de script en un PHP incluido. Solo tiene que escribirlo una vez y eso es tanto trabajo como llamar al complemento usando JavaScript.

rgb_life
fuente
@will, su solución parece mucho más limpia que la mía y me preocupa tener algunos errores si uso la mía, ya que utiliza .append (). Entonces, para usar esto, ¿puede llamar a esa función una vez para cada archivo de complemento que desee incluir?
rgb_life 01 de