[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 框架