1. 程式人生 > >Browserify使用指南(轉)

Browserify使用指南(轉)

zha 操作 func handbook -o uid dup pac events

讓瀏覽器加載Nodejs模塊

目前NPM上有二十多萬個NodeJS模塊,它們都是通過CMD的方式打包的,除了特定的可以使用CMD模塊加載器加載的模塊,大部分nodejs模塊無法直接使用到瀏覽器環境中。

Browserify是一個供瀏覽器環境使用的模塊打包工具,像在node環境一樣,也是通過require(‘modules‘)來組織模塊之間的引用和依賴,既可以引用npm中的模塊,也可以引用自己寫的模塊,然後打包成js文件,再在頁面中通過<script>標簽加載。

當然對於很多NodeJS模塊,比如涉及到io操作的模塊,就算通過browserify打包後肯定也無法運行在瀏覽器環境中,這種情況下就會用到為它們重寫的支持瀏覽器端的分支模塊,可以在browserify search搜索到這些模塊。

用例

比如寫一個入口main.js文件,使用require()來引用其它模塊,包括相對目錄中的‘./foo.js‘‘../lib/bar.js‘,還有在node_modules/目錄中的名為‘gamma‘的模塊。

browserify通過node’s module lookup algorithm來查找node_modules/中的模塊)

// main.js
var foo = require(‘./foo.js‘);
var bar = require(‘../lib/bar.js‘);
var gamma = require(‘gamma‘);

var elem = document.getElementById(‘result‘);
var x = foo(100) + bar(‘baz‘);
elem.textContent = gamma(x);

眾所周知,這些被引用的模塊會用通過module.exportsexports輸出它們的功能接口:

// foo.js
module.exports = function (n) { return n * 111 }

接下來就可以用browserify命令對它們進行打包了:

$ browserify main.js > bundle.js

main.js和它所引用的模塊會按依賴序列整體打包到bundle.js

browserify使用required來查找require()依賴隊列。

接下來,就可以在html中加載這個文件<script src="bundle.js"></script>

來運行了。

安裝Browserify

$ npm install -g browserify

通過命令行使用

Usage: browserify [entry files] {OPTIONS}

常用選項:

    --outfile, -o  指定打包後的輸出文件
                   如果不指定,將輸到stdout,比如shell

    --require, -r  通過模塊名或文件路徑指定需要打包到bundle中的其他模塊
                   Optionally use a colon separator to set the target

      --entry, -e  入口文件

     --ignore, -i  打包過程中忽略依賴的某個文件,當成空模塊打包,引用它不會報錯

    --exclude, -u  打包過程中排除依賴的某個文件,比忽略選項更嚴格,引用它會報錯

   --external, -x  指定某個文件不要打包到bundle,它可能會打包在其他的bundle中,比如jquery會打包到公共的bundle中

  --transform, -t  指定打包過程中使用的轉換模塊

    --command, -c  指定打包過程中使用的命令行轉換

  --standalone -s  生成UMD模式的bundle模塊,可以在AMD、CMD中使用

       --debug -d  生成source maps,並被註釋到bundle.js的尾部

       --help, -h  顯示幫助

高級選項:

  --insert-globals, --ig, --fast    [default: false]

    如果設置為true,會跳過代碼分析,強制在每個模塊的閉包作用域中插入如下參數
    process, global, __filename, and __dirname

    優點: 打包速度快
    缺點: 生成多余的參數

  --insert-global-vars, --igv

    需要在代碼分析中檢測和定義的全局變量,需要和--insert-globals一起使用
    默認包括 __filename,__dirname,process,Buffer,global 用逗號分隔

  --detect-globals, --dg            [default: true]

    在代碼分析過程中檢測全局變量 process, global, __filename, and __dirname

    優點: 像npm模塊那樣工作
    缺點: 打包速度慢

  --ignore-missing, --im            [default: false]

    忽略 `require()` 引用

  --noparse=FILE

    對於默寫確定不包含`require()`的文件,忽略他們的解析過程(比如jquery),加快打包速度

  --no-builtins

    如果打包後的文件要在node環境中使用,請使用這個選項,保證node內置模塊不被打包到bundle中

  --no-commondir

    不是用相對路徑,__filename,__dirname會被解析成絕對路徑

  --no-bundle-external

    不打包擴展模塊

  --bare

    --no-builtins --no-commondir --insert-global-vars "__filename,__dirname" 的別名
    如果bundle在node環境中運行,請使用--bare

  --no-browser-field, --no-bf

    忽略package.json中的browser屬性
    如果bundle在node環境中運行

  --node

    --bare --no-browser-field 的別名

  --full-paths

    所有模塊都是用絕對路徑進行引用

  --deps

    輸出模塊的依賴序列(一個數組)

  --list

    輸出所有模塊的路徑列表

  --extension=EXTENSION

    指定有效的模塊文件擴展名

  --global-transform=MODULE, -g MODULE

    指定一個全局的轉換模塊

  --plugin=MODULE, -p MODULE

    註冊一個插件模塊

如何在轉換模塊和插件再插入參數項:

  使用subarg語法在中括號中插入子命令,比如:

    -t [ foo -x 3 --beep ]

  會這樣執行

    foo(file, { x: 3, beep: true })

nodejs內置模塊的轉換

理想情況下,大部分不涉及io操作的模塊可以在瀏覽器中直接運行。

對於nodejs內置模塊,在require()它們的時候,會被轉換成如下模塊來打包,以適配瀏覽器環境。

  • assert
  • buffer
  • console
  • constants
  • crypto
  • domain
  • events
  • http
  • https
  • os
  • path
  • punycode
  • querystring
  • stream
  • string_decoder
  • timers
  • tty
  • url
  • util
  • vm
  • zlib

另外, 如果是用到了如下5個全局變量,它們會在打包過程中被改寫成可以適配瀏覽器環境的。

  • process
  • Buffer
  • global 全局變量window
  • __filename - 文件名
  • __dirname - 文件路徑

其他用例

在全局作用域中(模塊外部)引用指定模塊

$ browserify -r through -r duplexer -r ./my-file.js:my-module > bundle.js

在頁面中直接引用這些外部模塊

<script src="bundle.js"></script>
<script>
  var through = require(‘through‘);
  var duplexer = require(‘duplexer‘);
  var myModule = require(‘my-module‘);
  /* ... */
</script>

導出source maps文件

使用exorcist導出.js.map文件

$ browserify main.js --debug | exorcist bundle.js.map > bundle.js

導出多個包

如果多個頁面的打包結果中包含公共的模塊,可以將公共模塊(common.js)單獨打包出來,以節省請求流量並優化緩存策略

# beep.js
var robot = require(‘./robot.js‘);
console.log(robot(‘beep‘));
# boop.js
var robot = require(‘./robot.js‘);
console.log(robot(‘boop‘));

這兩個文件都引用了robot.js

# robot.js
module.exports = function (s) { return s.toUpperCase() + ‘!‘ };
# 把公共的模塊打包成common.js
$ browserify -r ./robot.js > static/common.js
$ browserify -x ./robot.js beep.js > static/beep.js
$ browserify -x ./robot.js boop.js > static/boop.js

如何引用?

<!--beep.html-->
<script src="common.js"></script>
<script src="beep.js"></script>
<!--boop.html-->
<script src="common.js"></script>
<script src="boop.js"></script>

上面這個用例,還可以用插件解決,會更方便

api

Browserify本身也是一個nodejs模塊,提供的方法大致和上面介紹的命令行選項相同,具體的api請參考browserify methods,這裏不再敖述。

var browserify = require(‘browserify‘);
var b = browserify();
b.add(‘./browser/main.js‘);
b.bundle().pipe(process.stdout);

events api

//當文件被進行打包時出發,可以用來監聽文件變化來重新進行打包
b.on(‘file‘, function (file, id, parent) {})
b.pipeline.on(‘file‘, function (file, id, parent) {})

// 當每個package.json被讀取時觸發
b.on(‘package‘, function (pkg) {})
b.pipeline.on(‘package‘, function (pkg) {})

// 當執行`.bundle()`時觸發
b.on(‘bundle‘, function (bundle) {})

// 當執行`.reset()`時觸發
b.on(‘reset‘, function () {})

// 當一個文件被轉換時觸
b.on(‘transform‘, function (tr, file) {})
b.pipeline.on(‘transform‘, function (tr, file) {})

package.json

browserify會先通過package.json中的"main"屬性來查找模塊入口,如果沒有"main"屬性,就在目錄中搜索"index.js"文件。當然,package.json中還定義了一些browserify特有的屬性:

browser屬性

“browser“屬性用來優先指定browserify打包是的模塊入口文件,這樣可以和"main"屬性區分開

"browser": "./browser.js"

還可以指定細分的打包替換文件

"browser": {
  "fs": "level-fs",
  "./lib/ops.js": "./browser/opts.js"
}

browserify.transform

package.json中指定轉換模塊,可以打包過程中自動執行

"browserify": { "transform": [ "brfs" ] }

使用插件

對於一些更先進的用例,轉換模塊並不能滿足需求,插件是更適合的選擇。插件是以包實例為其第一個參數,其他屬性作為後面的參數。插件可以用來做一些轉換模塊做不到的花哨功能。比如factor-bundle插件可以用來自動生成多個入口文件共用的common.js模塊。

$ browserify x.js y.js -p [ factor-bundle -o bundle/x.js -o bundle/y.js ]   > bundle/common.js

參考鏈接

  • Browserify插件列表
  • Browserify轉換列表
  • Browserify第三方工具
  • Browserify參考手冊
  • Browserify:瀏覽器加載Node.js模塊
  • 通過Browserify在瀏覽器中使用NodeJS模塊

轉自:http://zhaoda.net/2015/10/16/browserify-guide/

Browserify使用指南(轉)