节点式的需要在浏览器中的JavaScript?
浏览器中是否有任何JavaScript库提供与Node require
的相同的灵活性/模块性/易用性?
要提供更多的细节: require
的原因是如此之好,它是:
- 允许从其他位置dynamic加载代码(在我看来,在风格上更好,而不是链接HTML中的所有代码)
- 它为构build模块提供了一致的界面
- 模块很容易依赖于其他模块(所以我可以编写一个需要jQuery的API,这样我就可以使用
jQuery.ajax()
- 加载的javascript是有作用域的 ,这意味着我可以加载
var dsp = require("dsp.js");
我可以访问dsp.FFT
,这不会干扰我的本地var FFT
我还没有find一个有效的库。 我倾向于使用的解决方法是:
-
coffeescript-concat – 很容易要求其他的js,但是你必须编译它,这意味着它对于快速开发来说不是那么好(比如构buildAPI in-test)
-
RequireJS – 它很stream行,直接,解决1-3,但是缺less范围是一个真正的破产 (我相信head.js是相似的,因为它缺乏范围,但我从来没有任何机会使用它。同样, LABjs可以加载,
.wait()
可以.wait()
依赖关系问题,但是它仍然没有做范围界定)
据我所知,似乎有很多的dynamic和/或asynchronous加载的解决scheme,但他们往往有相同的范围问题,只是从HTML加载js。 更重要的是,我想要一种方法来加载JavaScript,根本不污染全局名称空间,但仍然允许我加载和使用库(就像节点的要求一样)。
编辑(我的答案):由于写这个,我已经广泛使用了RequireJS (现在有更清晰的文档)。 在我看来,RequireJS确实是正确的select。 我想澄清这个系统对那些和我一样困惑的人是如何工作的:
你可以在日常开发中使用require
。 一个模块可以是一个函数(通常是一个对象或一个函数)返回的任何东西,并且作为参数作用域。 您也可以使用r.js
将您的项目编译成单个文件进行部署(实际上,即使require
可以并行加载脚本,这几乎总是更快)。
RequireJS和node-style之间的主要区别在于像browserify(由tjamesonbuild议的一个很酷的项目)使用的是模块的devise和要求的方式:
- RequireJS使用AMD(asynchronous模块定义)。 在AMD中,
require
需要一个模块列表(javascript文件)来加载和callback函数。 当它加载了每个模块时,它将调用每个模块的callback作为callback的参数。 因此,它确实是asynchronous的,因此非常适合于networking。 - 节点使用CommonJS。 在CommonJS中,
require
是一个阻塞调用,它加载一个模块并将其作为一个对象返回。 这适用于Node,因为文件是从文件系统中读取的,速度足够快,但在networking上效果不佳,因为同步加载文件可能需要更长的时间。
在实践中,许多开发者在看到AMD之前就已经使用了Node(以及CommonJS)。 另外,许多库/模块是为CommonJS编写的(通过向导出对象添加东西)而不是AMD(通过从define
函数返回模块)。 因此,许多Node-turned-Web开发人员想要在Web上使用CommonJS库。 这是可能的,因为从<script>
标记加载被阻止。 像browserify这样的解决scheme采取CommonJS(节点)模块,并包装起来,所以你可以包含脚本标签。
因此,如果您正在为Web开发自己的多文件项目,我强烈build议RequireJS,因为它是真正的Web模块系统(尽pipe在公平的披露中,我发现AMD比CommonJS更自然)。 最近,这个区别变得不太重要,因为RequireJS现在允许你基本上使用CommonJS语法。 另外,RequireJS可以用来在Node中加载AMD模块(尽pipe我更喜欢node-amd-loader )。
退房恩德 。 它做了很多这个。
此外, browserify是相当不错的。 我已经使用了require-kiss并且可以工作。 有可能是其他人。
我不确定RequireJS。 它只是不一样的节点。 您可能会遇到从其他位置加载的问题,但可能会起作用。 只要有提供方法或者可以调用的东西。
TL; DR – 我会推荐browserify或require-kiss。
更新:
要求吻现在已经死了,作者已经把它删除了。 自从使用RequireJS以来,我一直没有问题。 要求吻的作者写了pakmanager和pakman 。 充分披露,我与开发人员合作。
我个人更喜欢RequireJS。 debugging起来要容易得多(您可以在开发中使用单独的文件,在生产中使用单个部署的文件),并且build立在一个坚实的“标准”上。
我写了一个小脚本,允许asynchronous和同步加载Javascript文件,这可能在这里有一些用处。 它没有依赖关系,并且与Node.js和CommonJS兼容。 您甚至可以将多个模块捆绑到一个文件中,以减less生产服务器上的HTTP请求。 用法很简单:
<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>
更多细节和代码可以在我的博客中find: http://pixelsvsbytes.com/2013/02/js-require-for-browsers-better-faster-stronger/代码也在GitHub上:; https:// github的.com / letorbi /冰沙/斑点/主/独立/ require.js
Ilya Kharlamov的一个变化很好的答案 ,用一些代码来使它和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
(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]; } })();
由于阻塞,最好不要用于生产。 (在node.js中,require()是一个阻塞调用)。
Webmake将节点式模块捆绑到浏览器,试试看。
这里是Lucio M. Tato的一个很好的答案的扩展,它允许recursion加载具有相对path的模块。
这里是一个github项目来容纳解决scheme和一个如何使用它的例子:
https://github.com/trausti/TKRequire.js
要使用TKRequire.js,请在标题中包含以下行
<script type =“text / javascript”src =“./ TKRequire.js”> </ script>
然后像在node.js中一样加载模块:
var MyModule = require(“./ relative / path / to / MyModule.js”);
Require-stub – 在浏览器中提供符合节点要求的require
,parsing模块和相对path。 使用类似于TKRequire(XMLHttpRequest)的技术。 所得到的代码是完全可浏览的,因为require-stub
可以作为watchify
的替代watchify
。