是什么 ? | : | a command-line tool that converts Node.js code to regular browser JavaScript code. |
开发语言 | : | Node.js |
官方主页 | : | http://browserify.org |
源码仓库 | : | https://github.com/browserify/browserify |
当Node.js流行起来以后,很多人都开始为Node.js编写模块, 随着编写的模块愈来越多,人们想把这些为Node.js开发的模块也能让它运行在Web浏览器中。Web浏览器和Node.js都是JavaScript Runtime, 在ES6 Module
出现之前,他们之间最大的不同是模块系统的不同,JavaScript
没有官方统一的模块系统,这就导致了在不同的JavaScript Runtime
之间的代码难以共用。
为了解决这个问题,我们有两种办法可以实现:
这两种办法中,使用UMD规范不够优雅, 我们还得记住这种奇怪的写法。而使用browserify
这个工具转换这个非常容易。
包管理器 | 安装命令 |
---|---|
npm | npm install -g browserify |
yarn | yarn global add browserify |
示例:
browserify xx.js > yy.js
browserify xx.js -o yy.js
假设,我们已经写好了两个Node.js的模块A
和B
,B
模块引用了A
模块。
A
模块的代码如下:
module.exports = 'A';
B
模块的代码如下:
var a = require('./A');
console.log(a);
现在,我们使用browserify
命令做转换,如下:
browserify B.js > bundle.js
现在A.js
、B.js
两个文件中的代码都被打包进bundle.js
中了, 这个bundle.js
就可以在Web浏览器中运行了。
这是不是很神奇?浏览器环境中可没有module
、module.exports
、require
这些的? 它是怎么执行的呢?要了解这个神奇的做法,就得看看转换后的bundle.js
文件的内容,为了便于观看,我做了格式化,如下:
(function () {
function r(e, n, t) {
function o(i, f) {
if (!n[i]) {
if (!e[i]) {
var c = "function" == typeof require && require;
if (!f && c)return c(i, !0);
if (u)return u(i, !0);
var a = new Error("Cannot find module '" + i + "'");
throw a.code = "MODULE_NOT_FOUND", a
}
var p = n[i] = {exports: {}};
e[i][0].call(p.exports, function (r) {
var n = e[i][1][r];
return o(n || r)
}, p, p.exports, r, e, n, t)
}
return n[i].exports
}
for (var u = "function" == typeof require && require, i = 0; i < t.length; i++)o(t[i]);
return o
}
return r
})()({
1: [function (require, module, exports) {
module.exports = 'A';
}, {}],
2: [function (require, module, exports) {
var a = require('./A');
console.log(a);
}, {"./A": 1}]
}, {}, [2]);
生成的bundle.js
文件写的有点绕,这主要是利用了JavaScript中的立即执行函数和函数可以且套定义的特点。 总的来说,它干了两件事情:
1、创造了module
、exports
、module.exports
对象、require
函数,使得语法上不会出现错误了。
2、将每个模块的代码都放到function (require, module, exports) {}
函数块中,并给这些模块标号。 所以,遇到require
函数调用,就被替换为function (require, module, exports) {}
函数调用了。