
在这个周末,npm超过了cpan,成为地球上最大的软件模块仓库.
npm的模块是用JavaScript语言编写的,但浏览器无法使用它,因为不支持CommonJS格式. 为了使浏览器使用这些模块,必须转换格式.

本文介绍了浏览器加载CommonJS的原理,并给出了一个非常简单的实现.
浏览器与CommonJS不兼容的根本原因是缺少四个Node.js环境变量.
只要可以提供这四个变量浏览器加载图片原理,浏览器就可以加载CommonJS模块.

这是一个简单的例子.
var module = {
exports: {}
};
(function(module, exports) {
exports.multiply = function (n) { return n * 1000 };
}(module, module.exports))
var f = module.exports.multiply;
f(5) // 5000
上面的代码提供了两个外部变量模块,并导出到立即执行函数,并将该模块放置在立即执行函数中. 模块的输出值放置在module.exports中,以便加载模块.
了解原理后,您可以制作工具. Browserify是当前最常用的CommonJS格式转换工具.

看一个main.js模块加载foo.js模块的示例.

// foo.js
module.exports = function(x) {
console.log(x);
};
// main.js
var foo = require("./foo");
foo("Hi");
使用以下命令,可以将main.js转换为浏览器可用的格式.
$ browserify main.js > compiled.js
Browserify到底能做什么?安装browser-unpack,您可以清楚地看到.
$ npm install browser-unpack -g
然后解压缩先前生成的compile.js.

$ browser-unpack < compiled.js
[
{
"id":1,
"source":"module.exports = function(x) {\n console.log(x);\n};",
"deps":{}
},
{
"id":2,
"source":"var foo = require(\"./foo\");\nfoo(\"Hi\");",
"deps":{"./foo":1},
"entry":true
}
]
如您所见,browerify将所有模块放入一个数组中,id属性是模块编号,source属性是模块的源代码,deps属性是模块的依赖项.
因为foo.js已加载到main.js中,所以deps属性指定./foo对应于模块1. 在执行期间,当浏览器遇到require('./ foo')语句时,它将自动执行源代码. 模块1的属性,并输出已执行的module.exports属性的值.
尽管Browserify功能强大,但无法在浏览器中操作,这有时很不方便.
基于mocha的内部实现,我制作了仅浏览器的CommonJS模块加载器tiny-browser-require. 完全没有命令行,只需将其放在浏览器中浏览器加载图片原理,所有代码仅超过30行.


其逻辑非常简单,它是将模块读入数组,而加载路径是模块ID.
function require(p){
var path = require.resolve(p);
var mod = require.modules[path];
if (!mod) throw new Error('failed to require "' + p + '"');
if (!mod.exports) {
mod.exports = {};
mod.call(mod.exports, mod, mod.exports, require.relative(path));
}
return mod.exports;
}
require.modules = {};
require.resolve = function (path){
var orig = path;
var reg = path + '.js';
var index = path + '/index.js';
return require.modules[reg] && reg
|| require.modules[index] && index
|| orig;
};
require.register = function (path, fn){
require.modules[path] = fn;
};
require.relative = function (parent) {
return function(p){
if ('.' != p.charAt(0)) return require(p);
var path = parent.split('/');
var segs = p.split('/');
path.pop();
for (var i = 0; i < segs.length; i++) {
var seg = segs[i];
if ('..' == seg) path.pop();
else if ('.' != seg) path.push(seg);
}
return require(path.join('/'));
};
};
使用时,首先将上面的代码放在页面上. 然后,将该模块放入下面的立即执行函数中,即可调用它.
<script src="require.js" />
<script>
require.register("moduleId", function(module, exports, require){
// Module code goes here
});
var result = require("moduleId");
</script>
让我们以之前的main.js加载foo.js为例.
require.register("./foo.js", function(module, exports, require){
module.exports = function(x) {
console.log(x);
};
});
var foo = require("./foo.js");
foo("Hi");
请注意,该库仅模拟三个变量: require,module和export. 如果该模块还使用全局变量或其他Node特定变量(例如process),则可以通过立即执行该函数来提供.
(结束)
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-200467-1.html
哇靠如果是我绝对淘到马云哭想买的东西太多了
但针对军事侵入中国海域包括南海的任何一个国家