web-dev-qa-db-fra.com

Le style de nœud nécessite un javascript dans le navigateur?

Existe-t-il des bibliothèques de javascript dans le navigateur qui offrent la même flexibilité/modularité/facilité d'utilisation que le require de Node?

Pour fournir plus de détails: la raison pour laquelle require est si bonne est qu'elle:

  1. Permet au code d'être chargé dynamiquement à partir d'autres emplacements (ce qui est à mon avis mieux sur le plan stylistique que de lier tout votre code dans le HTML)
  2. Il fournit une interface cohérente pour la construction de modules
  3. Il est facile pour les modules de dépendre d'autres modules (donc je pourrais écrire, par exemple, une API qui nécessite jQuery pour que je puisse utiliser jQuery.ajax()
  4. Le javascript chargé est scoped, ce qui signifie que je pourrais charger avec var dsp = require("dsp.js"); et que je serais en mesure d'accéder à dsp.FFT, Ce qui n'interférerait pas avec mon var FFT

Je n'ai pas encore trouvé de bibliothèque qui le fasse efficacement. Les solutions de contournement que j'ai tendance à utiliser sont les suivantes:

  • coffeescript-concat - il est assez facile d'exiger d'autres js, mais vous devez le compiler, ce qui signifie qu'il est moins efficace pour un développement rapide (par exemple, construire des API en test)

  • RequireJS - Il est populaire, simple et résout 1-3, mais le manque de cadrage est une vraie rupture (je crois head.js est similaire en ce sens qu'il manque la portée, même si je n'ai jamais eu l'occasion de l'utiliser. De même, LABjs peut se charger et .wait() atténue les problèmes de dépendance, mais ne fait toujours pas la portée)

Pour autant que je sache, il semble y avoir de nombreuses solutions pour le chargement dynamique et/ou asynchrone de javascript, mais elles ont tendance à avoir les mêmes problèmes de portée que le simple chargement des js à partir de HTML. Plus que toute autre chose, je voudrais un moyen de charger du javascript qui ne pollue pas du tout l'espace de noms global, mais me permet toujours de charger et d'utiliser des bibliothèques (tout comme le requiert le nœud).

EDIT (MA RÉPONSE): Depuis que j'ai écrit ceci, j'ai largement utilisé RequireJS (qui a maintenant une documentation beaucoup plus claire). RequireJS était vraiment le bon choix à mon avis. J'aimerais clarifier le fonctionnement du système pour les personnes aussi confuses que moi:

Vous pouvez utiliser require dans le développement quotidien. Un module peut être tout ce qui est retourné par une fonction (généralement un objet ou une fonction) et est délimité en tant que paramètre. Vous pouvez également compiler votre projet dans un fichier unique pour le déploiement à l'aide de r.js (En pratique, c'est presque toujours plus rapide, même si require peut charger des scripts en parallèle).

La principale différence entre RequireJS et le style de nœud nécessite, comme browserify (un projet sympa suggéré par tjameson), est la façon dont les modules sont conçus et requis:

  • RequireJS utilise AMD (Async Module Definition). Dans AMD, require prend une liste de modules (fichiers javascript) à charger et une fonction de rappel. Une fois qu'il a chargé chacun des modules, il appelle le rappel avec chaque module comme paramètre du rappel. Il est donc vraiment asynchrone et donc bien adapté au web.
  • Le nœud utilise CommonJS. Dans CommonJS, require est un appel de blocage qui charge un module et le renvoie en tant qu'objet. Cela fonctionne bien pour Node car les fichiers sont lus sur le système de fichiers, ce qui est assez rapide, mais fonctionne mal sur le Web car le chargement de fichiers de manière synchrone peut prendre beaucoup plus de temps.

En pratique, de nombreux développeurs ont utilisé Node (et donc CommonJS) avant de voir AMD. De plus, de nombreuses bibliothèques/modules sont écrits pour CommonJS (en ajoutant des éléments à un exports objet) plutôt que pour AMD (en renvoyant le module à partir de la fonction define). Par conséquent, de nombreux développeurs Node-Web tournés souhaitent utiliser les bibliothèques CommonJS sur le Web. Cela est possible, car le chargement à partir d'un La balise <script> Est bloquante. Des solutions comme browserify prennent des modules CommonJS (Node) et les regroupent pour que vous puissiez les inclure avec des balises de script.

Par conséquent, si vous développez votre propre projet multi-fichiers pour le Web, je recommande fortement RequireJS, car il s'agit vraiment d'un système de modules pour le Web (bien que dans une divulgation honnête, je trouve AMD beaucoup plus naturel que CommonJS). Récemment, la distinction est devenue moins importante, puisque RequireJS vous permet désormais d'utiliser essentiellement la syntaxe CommonJS. De plus, RequireJS peut être utilisé pour charger des modules AMD dans Node (bien que je préfère node-AMD-loader ).

71
Alex Churchill

Découvrez ender . Cela fait beaucoup de cela.

En outre, browserify est assez bon. J'ai utilisé require-kiss et cela fonctionne. Il y en a probablement d'autres.

Je ne suis pas sûr de RequireJS. Ce n'est tout simplement pas la même chose que celle du nœud. Vous pouvez rencontrer des problèmes de chargement à partir d'autres emplacements, mais cela peut fonctionner. Tant qu'il existe une méthode provide ou quelque chose qui peut être appelé.

TL; DR - Je recommanderais la navigation par navigateur ou l'exigence de baiser.

Mise à jour:

require-kiss est maintenant mort et l'auteur l'a supprimé. Depuis, j'utilise RequireJS sans problème. L'auteur de require-kiss a écrit pakmanager et pakman . Divulgation complète, je travaille avec le développeur.

Personnellement, j'aime mieux RequireJS. Il est beaucoup plus facile à déboguer (vous pouvez avoir des fichiers séparés en développement et un seul fichier déployé en production) et est construit sur un solide "standard".

15
beatgammit

J'ai écrit un petit script qui permet le chargement asynchrone et synchrone de fichiers Javascript, ce qui pourrait être utile ici. Il n'a pas de dépendances et est compatible avec Node.js et CommonJS. Vous pouvez même regrouper plusieurs modules dans un seul fichier pour réduire les requêtes HTTP sur les serveurs de production. L'utilisation est assez simple:

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

Plus de détails et le code peuvent être trouvés dans mon blog: http://pixelsvsbytes.com/2013/02/js-require-for-browsers-better-faster-stronger/ Le code est également sur GitHub: https://github.com/letorbi/tarp.require

13
Torben

Une variation de Ilya Kharlamov excellente réponse , avec du code pour le faire jouer Nice avec chrome outils de développement.

//
///- 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
Lucio M. Tato
(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];
    }
})();

Mieux vaut ne pas être utilisé en production à cause du blocage. (Dans node.js, require () est un appel bloquant, c'est bien).

5
Ilya Kharlamov

Require-stub - fournit un require compatible avec les nœuds dans le navigateur, résout les modules et les chemins relatifs. Utilise une technique similaire à TKRequire (XMLHttpRequest). Le code résultant est entièrement navigable, en ce que require-stub peut remplacer watchify.

1
dy_

Webmake regroupe les modules de style nœud au navigateur, essayez-le.

1
Mariusz Nowak

Voici une extension de la réponse fantastique de Lucio M. Tato qui permet le chargement récursif de modules avec des chemins relatifs.

Voici un projet github pour héberger la solution et un exemple de comment l'utiliser:

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

Pour utiliser TKRequire.js, incluez la ligne suivante dans votre en-tête

<script type = "text/javascript" src = "./ TKRequire.js"> </script>

Chargez ensuite les modules comme dans node.js:

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

0