[TOC]
随着JavaScript程序逐渐模块化,在ECMAScript 6推出官方的模块处理方案之前,有两种方案在实践中广泛采用:一种是AMD模块规范,针对模块的异步加载,主要用于浏览器端;另一种是CommonJS规范,针对模块的同步加载,主要用于服务器端,即node.js环境。
Browserify是一个node.js模块,主要用于改写现有的CommonJS模块,使得浏览器端也可以使用这些模块。使用下面的命令,在全局环境下安装Browserify。
~~~
$ npm install -g browserify
~~~
## 基本用法
先看一个例子。假定有一个很简单的CommonJS模块文件foo.js。
~~~
// foo.js
module.exports = function(x) {
console.log(x);
};
~~~
然后,还有一个main.js文件,用来加载foo模块。
~~~
// main.js
var foo = require("./foo");
foo("Hi");
~~~
使用Browserify,将main.js转化为浏览器可以加载的脚本compiled.js。
~~~
browserify main.js > compiled.js
# 或者
browserify main > compiled.js
# 或者
browserify main.js -o compiled.js
~~~
之所以转化后的文件叫做compiled.js,是因为该文件不仅包括了main.js,还包括了它所依赖的foo.js。两者打包在一起,保证浏览器加载时的依赖关系。
~~~
<script src="compiled.js"></script>
~~~
使用上面的命令,在浏览器中运行compiled.js,控制台会显示Hi。
我们再看一个在服务器端的backbone模块转为客户端backbone模块的例子。先安装backbone和它所依赖的jQuery模块。
~~~
npm install backbone jquery
~~~
然后,新建一个main.js文件。
~~~
// main.js
var Backbone = require('backbone');
var $ = Backbone.$ = require('jquery/dist/jquery')(window);
var AppView = Backbone.View.extend({
render: function(){
$('main').append('<h1>Browserify is a great tool.</h1>');
}
});
var appView = new AppView();
appView.render();
~~~
接着,使用browserify将main.js转为app.js。
~~~
browserify main.js -o app.js
~~~
app.js就可以直接插入HTML网页了。
~~~
<script src="app.js"></script>
~~~
注意,只要插入app.js一个文件就可以了,完全不需要再加载backbone.js和jQuery了。
## 管理前端模块
Browserify的主要作用是将CommonJS模块转为浏览器可以调用的格式,但是纯粹的前端模块,也可以用它打包。
首先,新建一个项目目录,添加package.json文件。
~~~
{
"name": "demo",
"version": "1.0.0"
}
~~~
接着,新建index.html。
~~~
<!doctype html>
<html>
<head>
<title>npm and jQuery demo</title>
</head>
<body>
<span class="title-tipso tipso_style" title="This is a loaded TIPSO!">
Roll over to see the tip
</span>
<script src="./bundle.js">
</body>
</html>
~~~
上面代码中的bundle.js,就是Browserify打包后将生成的文件。
然后,安装jquery和它的插件。
~~~
$ npm install --save jquery tipso
~~~
接着,新建一个文件entry.js。
~~~
global.jQuery = require('jquery');
require('tipso');
jQuery(function(){
jQuery('.title-tipso').tipso();
});
~~~
上面的文件中,第一行之所以要把jQuery写成global的属性,是为了转码之后,它可以变成一个全局变量。
最后,Browserify打包。
~~~
$ browserify entry.js --debug > bundle.jsOA
~~~
上面代码中,--debug参数表示在打包后的文件中加入source map以便除错。
这时,浏览器打开index.html,脚本已经可以运行。如果不希望将jQuery一起打包,而是通过CDN加载,可以使用browserify-shim模块。
另外一个问题是,某些jQuery插件还有自带的CSS文件,这时可以安装parcelify模块。
~~~
$ npm install -g parcelify
~~~
然后,在package.json中写入规则,声明CSS文件的位置。
~~~
"style": [
"./node_modules/tipso/src/tipso.css"
]
~~~
接着,运行parcelify进行CSS打包。
~~~
$ parcelify entry.js -c bundle.css
~~~
最后,将打包后的CSS文件插入index.html。
~~~
<link rel="stylesheet" href="bundle.css" />
~~~
## 生成前端模块
有时,我们只是希望将node.js的模块,移植到浏览器,使得浏览器端可以调用。这时,可以采用browserify的-r参数(--require的简写)。
~~~
browserify -r through -r ./my-file.js:my-module > bundle.js
~~~
上面代码将through和my-file.js(后面的冒号表示指定模块名为my-module)都做成了模块,可以在其他script标签中调用。
~~~
<script src="bundle.js"></script>
<script>
var through = require('through');
var myModule = require('my-module');
/* ... */
</script>
~~~
可以看到,-r参数的另一个作用,就是为浏览器端提供require方法。
## 脚本文件的实时生成
Browserify还可以实时生成脚本文件。
下面是一个服务器端脚本,启动Web服务器之后,外部用户每次访问这个脚本,它的内容是实时生成的。
~~~
var browserify = require('browserify');
var http = require('http');
http.createServer(function (req, res) {
if (req.url === '/bundle.js') {
res.setHeader('content-type', 'application/javascript');
var b = browserify(__dirname + '/main.js').bundle();
b.on('error', console.error);
b.pipe(res);
}
else res.writeHead(404, 'not found')
});
~~~
## browserify-middleware模块
上面是将服务器端模块直接转为客户端脚本,然后在网页中调用这个转化后的脚本文件。还有一种思路是,在运行时动态转换模块,这就需要用到[browserify-middleware模块](https://github.com/ForbesLindesay/browserify-middleware)。
比如,网页中需要加载app.js,它是从main.js转化过来的。
~~~
<!-- index.html -->
<script src="app.js"></script>
~~~
你可以在服务器端静态生成一个app.js文件,也可以让它动态生成。这就需要用browserify-middleware模块,服务器端脚本要像下面这样写。
~~~
var browserify = require('browserify-middleware');
var express = require('express');
var app = express();
app.get('/app.js', browserify('./client/main.js'));
app.get('/', function(req, res){
res.render('index.html');
});
~~~
## 参考链接
* Jack Franklin, [Dependency Management with Browserify](http://javascriptplayground.com/blog/2013/09/browserify/)
* Seth Vincent, [Using Browserify with Express](http://learnjs.io/blog/2013/12/22/express-and-browserify/)
* Patrick Mulder, [Browserify - Unix in the browser](http://thinkingonthinking.com/unix-in-the-browser/)
* Patrick Catanzariti, [Getting Started with Browserify](http://www.sitepoint.com/getting-started-browserify/)
* Lin Clark, [Using jQuery plugins with npm](http://blog.npmjs.org/post/112064849860/using-jquery-plugins-with-npm)
- 第一章 导论
- 1.1 前言
- 1.2 为什么学习JavaScript?
- 1.3 JavaScript的历史
- 第二章 基本语法
- 2.1 语法概述
- 2.2 数值
- 2.3 字符串
- 2.4 对象
- 2.5 数组
- 2.6 函数
- 2.7 运算符
- 2.8 数据类型转换
- 2.9 错误处理机制
- 2.10 JavaScript 编程风格
- 第三章 标准库
- 3.1 Object对象
- 3.2 Array 对象
- 3.3 包装对象和Boolean对象
- 3.4 Number对象
- 3.5 String对象
- 3.6 Math对象
- 3.7 Date对象
- 3.8 RegExp对象
- 3.9 JSON对象
- 3.10 ArrayBuffer:类型化数组
- 第四章 面向对象编程
- 4.1 概述
- 4.2 封装
- 4.3 继承
- 4.4 模块化编程
- 第五章 DOM
- 5.1 Node节点
- 5.2 document节点
- 5.3 Element对象
- 5.4 Text节点和DocumentFragment节点
- 5.5 Event对象
- 5.6 CSS操作
- 5.7 Mutation Observer
- 第六章 浏览器对象
- 6.1 浏览器的JavaScript引擎
- 6.2 定时器
- 6.3 window对象
- 6.4 history对象
- 6.5 Ajax
- 6.6 同域限制和window.postMessage方法
- 6.7 Web Storage:浏览器端数据储存机制
- 6.8 IndexedDB:浏览器端数据库
- 6.9 Web Notifications API
- 6.10 Performance API
- 6.11 移动设备API
- 第七章 HTML网页的API
- 7.1 HTML网页元素
- 7.2 Canvas API
- 7.3 SVG 图像
- 7.4 表单
- 7.5 文件和二进制数据的操作
- 7.6 Web Worker
- 7.7 SSE:服务器发送事件
- 7.8 Page Visibility API
- 7.9 Fullscreen API:全屏操作
- 7.10 Web Speech
- 7.11 requestAnimationFrame
- 7.12 WebSocket
- 7.13 WebRTC
- 7.14 Web Components
- 第八章 开发工具
- 8.1 console对象
- 8.2 PhantomJS
- 8.3 Bower:客户端库管理工具
- 8.4 Grunt:任务自动管理工具
- 8.5 Gulp:任务自动管理工具
- 8.6 Browserify:浏览器加载Node.js模块
- 8.7 RequireJS和AMD规范
- 8.8 Source Map
- 8.9 JavaScript 程序测试
- 第九章 JavaScript高级语法
- 9.1 Promise对象
- 9.2 有限状态机
- 9.3 MVC框架与Backbone.js
- 9.4 严格模式
- 9.5 ECMAScript 6 介绍
- 附录
- 10.1 JavaScript API列表
- 草稿一:函数库
- 11.1 Underscore.js
- 11.2 Modernizr
- 11.3 Datejs
- 11.4 D3.js
- 11.5 设计模式
- 11.6 排序算法
- 草稿二:jQuery
- 12.1 jQuery概述
- 12.2 jQuery工具方法
- 12.3 jQuery插件开发
- 12.4 jQuery.Deferred对象
- 12.5 如何做到 jQuery-free?
- 草稿三:Node.js
- 13.1 Node.js 概述
- 13.2 CommonJS规范
- 13.3 package.json文件
- 13.4 npm模块管理器
- 13.5 fs 模块
- 13.6 Path模块
- 13.7 process对象
- 13.8 Buffer对象
- 13.9 Events模块
- 13.10 stream接口
- 13.11 Child Process模块
- 13.12 Http模块
- 13.13 assert 模块
- 13.14 Cluster模块
- 13.15 os模块
- 13.16 Net模块和DNS模块
- 13.17 Express框架
- 13.18 Koa 框架