gratis - ¿Estilo de nodo requiere para javascript en el navegador?
examen practico de javascript (7)
¿Hay bibliotecas para javascript en el navegador que ofrezcan la misma flexibilidad / modularidad / facilidad de uso que Node require
?
Para proporcionar más detalles: la razón que require
es tan buena es que:
- 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)
- Proporciona una interfaz consistente para construir módulos.
- Es fácil para los módulos depender de otros módulos (por lo que podría escribir, por ejemplo, una API que requiera jQuery para poder usar
jQuery.ajax()
- El javascript cargado tiene un ámbito , lo que significa que podría cargar con
var dsp = require("dsp.js");
y podría acceder adsp.FFT
, que no interferiría con mivar FFT
localvar FFT
Todavía tengo que encontrar una biblioteca que haga esto de manera efectiva. Las soluciones que tiendo a usar son:
coffeescript-concat : es bastante fácil requerir otros js, pero hay que compilarlo, lo que significa que es menos bueno para un desarrollo rápido (por ejemplo, compilación de API en la prueba)
RequireJS : es popular, directo y resuelve 1-3, pero la falta de alcance es un head.js (creo que head.js es similar en que carece de alcance, aunque nunca he tenido ocasión de usarlo). De manera similar, los LABjs pueden cargar y
.wait()
soluciona los problemas de dependencia, pero todavía no tiene alcance)
Por lo que puedo decir, parece que hay muchas soluciones para la carga dinámica y / o asíncrona de javascript, pero tienden a tener los mismos problemas de alcance que la carga de js desde HTML. Más que nada, me gustaría una forma de cargar javascript que no contamine el espacio de nombres global, pero que me permita cargar y usar bibliotecas (tal como lo requiere el nodo).
EDITAR (MI RESPUESTA): Desde que escribí esto, he usado ampliamente RequireJS (que ahora tiene una documentación mucho más clara). 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:
Puedes usar el require
en el desarrollo diario. Un módulo puede ser cualquier cosa devuelta por una función (normalmente un objeto o una función) y se incluye como parámetro. También puede compilar su proyecto en un solo archivo para su implementación utilizando r.js
(en la práctica, esto es casi siempre más rápido, aunque se pueden cargar scripts en paralelo).
La principal diferencia entre RequireJS y el estilo de nodo que requiere browserify (un proyecto genial sugerido por tjameson) es la forma en que se diseñan y requieren los módulos:
- RequireJS utiliza AMD (Definición del módulo asíncrono). En AMD, se
require
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 realmente asíncrono y, por lo tanto, muy adecuado para 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 síncrona puede llevar mucho más tiempo.
En la práctica, muchos desarrolladores han usado Node (y, por lo tanto, CommonJS) antes de que vean AMD. Además, muchas bibliotecas / módulos se escriben para CommonJS (agregando cosas a un objeto de exports
) en lugar de para AMD (devolviendo el módulo desde la función de define
). Por lo tanto, muchos desarrolladores de Nodo convertido en web desean utilizar las bibliotecas CommonJS en la web. Esto es posible, ya que la carga desde una etiqueta <script>
está bloqueando. Las 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 de archivos múltiples para la web, le recomiendo RequireJS, ya que es realmente un sistema de módulos para la web (aunque en una divulgación justa, creo que AMD es 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 de CommonJS. Además, RequireJS se puede usar para cargar módulos AMD en el nodo (aunque prefiero node-amd-loader ).
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 alojar 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
<script type = "text / javascript" src = "./ TKRequire.js"> </script>
Luego cargue los módulos como en node.js:
var MyModule = require ("./ relative / path / to / MyModule.js");
Echa un vistazo a ender . Hace mucho de esto.
Además, browserify es bastante bueno. He usado require-kiss y funciona. Probablemente hay otros.
No estoy seguro de RequireJS. Simplemente no es lo mismo que el de nodo. Puede tener problemas con la carga desde otras ubicaciones, pero podría funcionar. Mientras exista un método de provisión o algo que pueda ser llamado.
TL; DR : recomiendo browserify o require-kiss.
Actualizar:
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 RequireJS mejor. Es mucho más fácil de depurar (puede tener archivos separados en desarrollo y un solo archivo implementado en producción) y se basa en un "estándar" sólido.
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>
Se pueden encontrar más detalles y el código en mi blog: http://pixelsvsbytes.com/2013/02/js-require-for-browsers-better-faster-stronger/ El código también está en GitHub: https://github.com/letorbi/smoothie/blob/master/standalone/require.js
Una variación de la gran respuesta de Ilya Kharlamov , con algunos códigos para que funcione 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
Require-stub : proporciona un require
cumple con los nodos en el navegador, resuelve los módulos y las rutas relativas. Utiliza una técnica similar a TKRequire (XMLHttpRequest). El código resultante es totalmente identificable por el navegador, ya que require-stub
puede servir como un reemplazo para watchify
.
Webmake agrupa módulos de estilo de nodo al navegador, pruébalo.
(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];
}
})();
Mejor no ser utilizado en la producción debido al bloqueo. (En node.js, require () es una llamada de bloqueo está bien).