¿Requiere un estilo de nodo para javascript en el navegador?


¿Hay alguna biblioteca para javascript en el navegador que proporcione la misma flexibilidad/modularidad/facilidad de uso que el Nodo require?

Para proporcionar más detalles: la razón require es tan buena es que: {[16]]}

  1. Permite que el código se cargue dinámicamente desde otras ubicaciones (lo cual es estilísticamente mejor, en mi opinión, que vincular todo su código en el HTML)
  2. Proporciona una interfaz consistente para construir módulos
  3. Es fácil para los módulos depender de otros módulos (así que podría escribir, por ejemplo, una API que requiere jQuery para poder usar jQuery.ajax()
  4. Loaded javascript es scoped , lo que significa que podría cargar con var dsp = require("dsp.js"); y podría acceder a dsp.FFT, lo que no interferiría con mi var FFT

Todavía tengo que encontrar una biblioteca que haga esto de manera efectiva. Las soluciones que tiendo a usar son:

  • Coffeescript-concat 's es bastante fácil requerir otro js, pero tienes que compilarlo, lo que significa que es menos bueno para el desarrollo rápido (por ejemplo, la construcción de API en la prueba)

  • RequireJS -- Es popular, sencillo, y resuelve 1-3, pero la falta de definición de alcance es un real deal-breaker (creo cabeza.js es similar en que carece de alcance, aunque nunca he tenido ocasión de usarlo. Del mismo modo, LABjs puede cargar y .wait() apacigua los problemas de dependencia, pero aún no hace el alcance)

Por lo que puedo decir, hay parecen ser muchas soluciones para la carga dinámica y / o asíncrona de javascript, pero tienden a tener los mismos problemas de alcance que solo cargar el js desde HTML. Más que cualquier otra cosa, me gustaría una forma de cargar javascript que no contamine el espacio de nombres global en absoluto, pero todavía me permite cargar y usar bibliotecas (al igual que lo hace require de node).

EDITAR (MI RESPUESTA): Desde que escribí esto, he usado ampliamente RequireJS (que ahora tiene mucho más claro documentación). RequireJS realmente fue la elección correcta en mi opinión. Me gustaría aclarar cómo funciona el sistema para las personas que están tan confundidas como yo:

Puede usar require en el desarrollo diario. Un módulo puede ser cualquier cosa devuelta por una función (típicamente un objeto o una función) y es objeto como parámetro. También puede compilar su proyecto en un solo archivo para su implementación usando r.js (en la práctica esto es casi siempre más rápido, a pesar de que require puede cargar scripts en paralelo).

La principal diferencia entre RequireJS y require estilo nodo como browserify (un proyecto genial sugerido por tjameson) utiliza es la forma en que los módulos son diseñados y requeridos:

  • RequireJS usa AMD (Definición de Módulo Async). En AMD, require toma una lista de módulos (archivos javascript) para cargar y una función de devolución de llamada. Cuando ha cargado cada uno de los módulos, llama a la devolución de llamada con cada módulo como un parámetro a la devolución de llamada. Por lo tanto es verdaderamente asíncrono y por lo tanto bien adaptado a la web.
  • El nodo
  • usa CommonJS. En CommonJS, require es una llamada de bloqueo que carga un módulo y lo devuelve como un objeto. Esto funciona bien para Node porque los archivos se leen fuera del sistema de archivos, que es lo suficientemente rápido, pero funciona mal en la web porque cargar archivos de forma sincrónica puede tomar mucho más tiempo.

En la práctica, muchos desarrolladores han usado Node (y por lo tanto CommonJS) antes de ver AMD. Además, muchas bibliotecas/módulos están escritos para CommonJS (añadiendo cosas a un objeto exports) en lugar de para AMD (devolviendo el módulo desde la función define). Por lo tanto, muchos desarrolladores de Nodos convertidos en web quieren usar bibliotecas CommonJS en la web. Esto es posible, ya que cargar desde una etiqueta <script> está bloqueando. Soluciones como browserify toman módulos CommonJS (Nodo) y los envuelven para que pueda incluirlos con etiquetas de script.

Por lo tanto, si está desarrollando su propio proyecto multi-archivo para la web, le recomiendo encarecidamente RequireJS, ya que es realmente un sistema de módulos para la web (aunque en fair disclosure, encuentro AMD mucho más natural que CommonJS). Recientemente, la distinción se ha vuelto menos importante, ya que RequireJS ahora le permite usar esencialmente la sintaxis CommonJS. Además, RequireJS se puede usar para cargar módulos AMD en Node (aunque prefiero node-amd-loader).

Author: Alex Churchill, 2011-08-07

7 answers

Echa un vistazo a ender. Hace mucho de esto.

Además, browserify es bastante bueno. He usado require-kiss y funciona. Probablemente haya otros.

No estoy seguro sobre RequireJS. No es lo mismo que el nodo. Puede tener problemas con la carga desde otras ubicaciones, pero podría funcionar. Siempre y cuando haya un método de proporcionar o algo que se pueda llamar.

TL; DR - Yo recomendaría browserify o requiere-beso.

Actualización:

Require-kiss ahora está muerto, y el autor lo ha eliminado. Desde entonces he estado usando RequireJS sin problemas. El autor de require-kiss escribió pakmanager y pakman . Revelación completa, trabajo con el desarrollador.

Personalmente me gusta más RequireJS. Es mucho más fácil depurar (puede tener archivos separados en desarrollo y un solo archivo desplegado en producción) y está construido sobre un sólido "estándar".

 14
Author: beatgammit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-12 22:23:23

Escribí un pequeño script que permite la carga asíncrona y síncrona de archivos Javascript, que podría ser de alguna utilidad aquí. No tiene dependencias y es compatible con Node.js & CommonJS. Incluso puede agrupar varios módulos en un archivo para reducir las solicitudes HTTP en los servidores de producción. El uso es bastante fácil:

<script type="text/javascript" src="require.js"></script>
<script type="text/javascript">
    var ModuleA = require('modulea') // Sync loading of a script in the module directory
    ModuleA.funcA();

    require('./path/moduleb.js', callbackB); // Async loading of a script anywhere else
    function callbackB(ModuleB) {
        ModuleB.funcB();
    }
</script>

Más detalles y el código se pueden encontrar en mi blog: http://pixelsvsbytes.com/2013/02/js-require-for-browsers-better-faster-stronger / El código también es en GitHub: https://github.com/letorbi/smoothie/blob/master/standalone/require.js

 11
Author: Torben,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-22 03:48:01

Una variación de Ilya Kharlamov gran respuesta, con un poco de código para que juegue bien con las herramientas de desarrollo de Chrome.

//
///- REQUIRE FN
// equivalent to require from node.js
function require(url){
    if (url.toLowerCase().substr(-3)!=='.js') url+='.js'; // to allow loading without js suffix;
    if (!require.cache) require.cache=[]; //init cache
    var exports=require.cache[url]; //get from cache
    if (!exports) { //not cached
            try {
                exports={};
                var X=new XMLHttpRequest();
                X.open("GET", url, 0); // sync
                X.send();
                if (X.status && X.status !== 200)  throw new Error(X.statusText);
                var source = X.responseText;
                // fix (if saved form for Chrome Dev Tools)
                if (source.substr(0,10)==="(function("){ 
                    var moduleStart = source.indexOf('{');
                    var moduleEnd = source.lastIndexOf('})');
                    var CDTcomment = source.indexOf('//@ ');
                    if (CDTcomment>-1 && CDTcomment<moduleStart+6) moduleStart = source.indexOf('\n',CDTcomment);
                    source = source.slice(moduleStart+1,moduleEnd-1); 
                } 
                // fix, add comment to show source on Chrome Dev Tools
                source="//@ sourceURL="+window.location.origin+url+"\n" + source;
                //------
                var module = { id: url, uri: url, exports:exports }; //according to node.js modules 
                var anonFn = new Function("require", "exports", "module", source); //create a Fn with module code, and 3 params: require, exports & module
                anonFn(require, exports, module); // call the Fn, Execute the module
                require.cache[url]  = exports = module.exports; //cache obj exported by module
            } catch (err) {
                throw new Error("Error loading module "+url+": "+err);
            }
    }
    return exports; //require returns object exported by module
}
///- END REQUIRE FN
 7
Author: Lucio M. Tato,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:24
(function () {
    // c is cache, the rest are the constants
    var c = {},s="status",t="Text",e="exports",E="Error",r="require",m="module",S=" ",w=window;
    w[r]=function R(url) {
        url+=/.js$/i.test(url) ? "" : ".js";// to allow loading without js suffix;
        var X=new XMLHttpRequest(),module = { id: url, uri: url }; //according to the modules 1.1 standard
        if (!c[url])
            try {
                X.open("GET", url, 0); // sync
                X.send();
                if (X[s] && X[s] != 200) 
                    throw X[s+t];
                Function(r, e, m, X['response'+t])(R, c[url]={}, module); // Execute the module
                module[e] && (c[url]=module[e]);
            } catch (x) {
                throw w[E](E+" in "+r+": Can't load "+m+S+url+":"+S+x);
            }
        return c[url];
    }
})();

Es mejor no ser utilizado en la producción debido al bloqueo. (In node.js, require () es una llamada de bloqueo está bien).

 5
Author: Ilya Kharlamov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-05 01:29:06

Webmake agrupa módulos estilo nodo al Navegador, inténtalo.

 1
Author: Mariusz Nowak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-26 18:58:49

Require-stub - proporciona require compatible con nodos en el navegador, resuelve tanto los módulos como las rutas relativas. Utiliza una técnica similar a TKRequire (XMLHttpRequest). El código resultante es completamente browserifyable, ya que require-stub puede servir como un reemplazo para watchify.

 1
Author: Dmitry_F,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-11 07:15:58

Aquí hay una extensión de la fantástica respuesta de Lucio M. Tato que permite la carga recursiva de módulos con rutas relativas.

Aquí hay un proyecto de github para albergar la solución y un ejemplo de cómo usarla:

Https://github.com/trausti/TKRequire.js

Para usar TKRequire.js, incluya la siguiente línea en su encabezado

Luego cargue los módulos como en nodo.js:

Var MyModule = require("./ relative/path/to / MyModule.js");

 0
Author: Trausti Kristjansson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-26 13:24:47