亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

使用Browserify配合jQuery進行編程的超級指南

2019-11-20 11:58:30
字體:
來源:轉載
供稿:網友

引言
1. manually

以前,我新開一個網頁項目,然后想到要用jQuery,我會打開瀏覽器,然后找到jQuery的官方網站,點擊那個醒目的“Download jQuery”按鈕,下載到.js文件,然后把它丟在項目目錄里。在需要用到它的地方,這樣用<script>引入它:

<script src="path/to/jquery.js"></script>

2. Bower

后來,我開始用Bower這樣的包管理工具。所以這個過程變成了:先打開命令行用bower安裝jQuery。

bower install jquery

再繼續用<script>引入它。

<script src="bower_components/jquery/dist/jquery.js"></script>

3. npm&Browserify

現在,我又有了新的選擇,大概是這樣:

命令行用npm安裝jQuery。

npm install jquery

在需要用到它的JavaScript代碼里,這樣引入它:

var $ = require("jquery");

沒錯,這就是使用npm的包的一般方法。但特別的是,這個npm的包是我們熟知的jquery,而它將用在瀏覽器中。

Browserify,正如其名字所體現的動作那樣,讓原本屬于服務器端的Node及npm,在瀏覽器端也可使用。

顯然,上面的過程還沒結束,接下來是Browserify的工作(假定上面那段代碼所在的文件叫main.js):

browserify main.js -o bundle.js

最后,用<script>引用Browserify生成的bundle.js文件。

<script src="bundle.js"></script>

這就是依托Browserify建立起來的第三選擇。

等下,怎么比以前變復雜了?
CommonJS風格的模塊及依賴管理

其實,在這個看起來更復雜的過程中,require()具有非凡的意義。

Browserify并不只是一個讓你輕松引用JavaScript包的工具。它的關鍵能力,是JavaScript模塊及依賴管理。(這才是為師的主業)

就模塊及依賴管理這個問題而言,已經有RequireJS和國內的Sea.js這些優秀的作品。而現在,Browserify又給了我們新的選擇。
Browserify參照了Node中的模塊系統,約定用require()來引入其他模塊,用module.exports來引出模塊。在我看來,Browserify不同于RequireJS和Sea.js的地方在于,它沒有著力去提供一個“運行時”的模塊加載器,而是強調進行預編譯。預編譯會帶來一個額外的過程,但對應的,你也不再需要遵循一定規則去加一層包裹。因此,相比較而言,Browserify提供的組織方式更簡潔,也更符合CommonJS規范。

像寫Node那樣去組織你的JavaScript,Browserify會讓它們在瀏覽器里正常運行的。
安裝及使用
命令行形式

命令行形式是官方貼出來的用法,因為看起來最簡單。

Browserify本身也是npm,通過npm的方式安裝:

npm install -g browserify

這里-g的參數表示全局,所以可以在命令行內直接使用。接下來,運行browserify命令到你的.js文件(比如entry.js):

browserify entry.js -o bundle.js

Browserify將遞歸分析你的代碼中的require(),然后生成編譯后的文件(這里的bundle.js)。在編譯后的文件內,所有JavaScript模塊都已合并在一起且建立好了依賴關系。最后,你在html里引用這個編譯后的文件(喂,和引言里的一樣?。?/p>

<script src="bundle.js"></script>

有關這個編譯命令的配置參數,請參照node-browserify#usage。如果你想要做比較精細的配置,命令行形式可能會不太方便。這種時候,推薦結合Gulp使用。
+ Gulp形式

結合Gulp使用時,你的Browserify只安裝在某個項目內:

npm install browserify --save-dev

建議加上后面的--save-dev以保存到你項目的package.json里。

接下來是gulpfile.js的部分,下面是一個簡單示例:

var gulp = require("gulp");var browserify = require("browserify");var sourcemaps = require("gulp-sourcemaps");var source = require('vinyl-source-stream');var buffer = require('vinyl-buffer');gulp.task("browserify", function () { var b = browserify({  entries: "./javascripts/src/main.js",  debug: true }); return b.bundle()  .pipe(source("bundle.js"))  .pipe(buffer())  .pipe(sourcemaps.init({loadMaps: true}))  .pipe(sourcemaps.write("."))  .pipe(gulp.dest("./javascripts/dist"));});

可以看到,Browserify是獨立的,我們需要直接使用它的API,并將它加入到Gulp的任務中。

在上面的代碼中,debug: true是告知Browserify在運行同時生成內聯sourcemap用于調試。引入gulp-sourcemaps并設置loadMaps: true是為了讀取上一步得到的內聯sourcemap,并將其轉寫為一個單獨的sourcemap文件。vinyl-source-stream用于將Browserify的bundle()的輸出轉換為Gulp可用的vinyl(一種虛擬文件格式)流。vinyl-buffer用于將vinyl流轉化為buffered vinyl文件(gulp-sourcemaps及大部分Gulp插件都需要這種格式)。

這樣配置好之后,直接運行gulp browserify就可以得到結果了,可能像這樣:

2015728152450337.png (526×74)

如果你的代碼比較多,可能像上圖這樣一次編譯需要1s以上,這是比較慢的。這種時候,推薦使用watchify。它可以在你修改文件后,只重新編譯需要的部分(而不是Browserify原本的全部編譯),這樣,只有第一次編譯會花些時間,此后的即時變更刷新則十分迅速。

有關更多Browserify + Gulp的示例,請參考Gulp Recipes。
特性及簡要原理

使用Browserify來組織JavaScript,有什么要注意的地方嗎?

要回答這個問題,我們先看看Browserify到底做了什么。下面是一個比較詳細的例子。

項目內現在用到2個.js文件,它們存在依賴關系,其內容分別是:
name.js

module.exports = "aya";

main.js

var name = require("./name");console.log("Hello! " + name);

然后對main.js運行Browserify,得到的bundle.js的文件內容是這樣的:
bundle.js

(function e(t, n, r) { // ...})({ 1: [function (require, module, exports) {  var name = require("./name");  console.log("Hello! " + name); }, {"./name": 2}], 2: [function (require, module, exports) {  module.exports = "aya"; }, {}]}, {}, [1])//# sourceMappingURL=bundle.js.map

請先忽略掉省略號里的部分。然后,它的結構就清晰多了??梢钥吹?,整體是一個立即執行的函數(IIFE),該函數接收了3個參數。其中第1個參數比較復雜,第2、3個參數在這里分別是{}和[1]。
模塊map

第1個參數是一個Object,它的每一個key都是數字,作為模塊的id,每一個數字key對應的值是長度為2的數組??梢钥闯觯懊娴膍ain.js中的代碼,被function(require, module, exports){}這樣的結構包裝了起來,然后作為了key1數組里的第一個元素。類似的,name.js中的代碼,也被包裝,對應到key2。

數組的第2個元素,是另一個map對應,它表示的是模塊的依賴。main.js在key1,它依賴name.js,所以它的數組的第二個元素是{"./name": 2}。而在key2的name.js,它沒有依賴,因此其數組第二個元素是空Object{}。

因此,這第1個復雜的參數,攜帶了所有模塊的源碼及其依賴關系,所以叫做模塊map。
包裝

前面提到,原有的文件中的代碼,被包裝了起來。為什么要這樣包裝呢?

因為,瀏覽器原生環境中,并沒有require()。所以,需要用代碼去實現它(RequireJS和Sea.js也做了這件事)。這個包裝函數提供的3個參數,require、module、exports,正是由Browserify實現了特定功能的3個關鍵字。
緩存

第2個參數幾乎總是空的{}。它如果有的話,也是一個模塊map,表示本次編譯之前被加載進來的來自于其他地方的內容?,F階段,讓我們忽略它吧。
入口模塊

第3個參數是一個數組,指定的是作為入口的模塊id。前面的例子中,main.js是入口模塊,它的id是1,所以這里的數組就是
[1]。數組說明其實還可以有多個入口,比如運行多個測試用例的場景,但相對來說,多入口的情況還是比較少的。
實現功能

還記得前面忽略掉的省略號里的代碼嗎?這部分代碼將解析前面所說的3個參數,然后讓一切運行起來。這段代碼是一個函數,來自于browser-pack項目的prelude.js。令人意外的是,它并不復雜,而且寫有豐富的注釋,很推薦你自行閱讀。
所以,到底要注意什么?

到這里,你已經看過了Browserify是如何工作的。是時候回到前面的問題了。首先,在每個文件內,不再需要自行包裝。

你可能已經很習慣類似下面這樣的寫法:

;(function(){ // Your code here.}());

但你已經了解到,Browserify的編譯會將你的代碼封裝在局部作用域內,所以,你不再需要自己做這個事情,像這樣會更好:

// Your code here.

類似的,如果你想用"use strict";啟用嚴格模式,直接寫在外面就可以了,這表示在某個文件的代碼范圍內啟用嚴格模式。

其次,保持局部變量風格。我們很習慣通過window.jQuery和window.$這樣的全局變量來訪問jQuery這樣的庫,但如果使用Browserify,它們都應只作為局部變量:

var $ = require("jquery");$("#alice").text("Hello!");

這里的$就只存在于這個文件的代碼范圍內(獨立的作用域)。如果你在另一個文件內要使用jQuery,需要按照同樣的方式去require()。

然而,新的問題又來了,既然jQuery變成了這種局部變量的形式,那我們熟悉的各種jQuery插件要如何使用呢?
browserify-shim

你一定熟悉這樣的jQuery插件使用方式:

<script src="jquery.js"></script><script src="jquery.plugin.js"></script><script> // Now the jQuery plugin is available.</script>

很多jQuery插件是這樣做的:默認window.jQuery存在,然后取這個全局變量,把自己添加到jQuery中。顯然,這在Browserify的組織方式里是沒法用的。

為了讓這樣的“不兼容Browserify”(其實是不兼容CommonJS)的JavaScript模塊(如插件)也能為Browserify所用,于是有了browserify-shim。

下面,以jQuery插件jquery.pep.js為例,請看browserify-shim的使用方法。
使用示例

安裝browserify-shim:

npm install browserify-shim --save-dev

然后在package.json中做如下配置:

"browserify": { "transform": [ "browserify-shim" ]},"browser": { "jquery.pep" : "./vendor/jquery.pep.js"},"browserify-shim": { "jquery.pep" : { "depends": ["jquery:jQuery"] }}

最后是.js中的代碼:

var $ = require("jquery");require("jquery.pep");$(".move-box").pep();

完成!到此,經過Browserify編譯后,將可以正常運行這個jQuery插件。

這是一個怎樣的過程呢?

在本例中,jQuery使用的是npm里的,而jquery.pep.js使用的是一個自己下載的文件(它與很多jQuery插件一樣,還沒有發布到npm)。查看jquery.pep.js源碼,注意到它用了這樣的包裝:

;(function ( $, window, undefined ) { // ...}(jQuery, window));

可以看出,它默認當前環境中已存在一個變量jQuery(如果不存在,則報錯)。package.json中的"depends": ["jquery:jQuery"]是為它添加依賴聲明,前一個jquery表示require("jquery"),后一個jQuery則表示將其命名為jQuery(賦值語句)。這樣,插件代碼運行的時候就可以正常找到jQuery變量,然后將它自己添加到jQuery中。

實際上,browserify-shim的配置并不容易。針對代碼包裝(盡管都不兼容CommonJS,但也存在多種情況)及使用場景的不同,browserify-shim有不同的解決方案,本文在此只介紹到這。

關于配置的更多說明,請參照browserify-shim官方文檔。更多參考可以查看browserify shim recipes。此外,如果你覺得browserify-shim有些難以理解或者對它的原理也有興趣,推薦閱讀這篇Stack Overflow上的回答。

當然,對于已經處理了CommonJS兼容的庫或插件(比如已經發布到npm),browserify-shim是不需要的。
其實還有的更多transform

在前面browserify-shim的例子中,"browserify": {"transform": [ "browserify-shim" ]}其實是Browserify的配置??梢钥闯?,browserify-shim只是Browserify的其中一種transform。在它之外,還有很多的transform可用,分別應對不同的需求,使Browserify的體系更為完善。

比如,還記得本文引言里的Bower嗎?debowerify可以讓通過Bower安裝的包也可以用require()引用。npm和bower同為包管理工具,Browserify表示你們都是我的翅膀。
一點提示

Browserify是靜態分析編譯工具,因此不支持動態require()。例如,下面這樣是不可以的:

var lang = "zh_cn";var i18n = require("./" + lang);

文檔資料

有關Browserify更詳細的說明文檔,請看browserify-handbook
結語

我覺得Browserify很有趣,它用了這樣一個名字,讓你覺得它好像只是一個Node的瀏覽器端轉化工具。為此,它還完成了Node中大部分核心庫的瀏覽器端實現。但實際上,它走到了更遠的地方,并在JavaScript模塊化開發這個重要的領域中,創立了一個全新的體系。

喜歡CommonJS的簡潔風格?請嘗試Browserify!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
成人国产精品久久久久久亚洲| 久久激情视频久久| 国产精品jizz在线观看麻豆| 亚洲欧洲日韩国产| 亚洲自拍高清视频网站| 欧美一级大片在线免费观看| 日韩美女视频免费看| 久久久久女教师免费一区| 欧美日韩成人网| 国产精品久久久久久久久久久久久久| 91在线免费看网站| 国产精品日日做人人爱| 国产精品久久久久aaaa九色| 91精品国产99| 中文字幕日本欧美| www.亚洲人.com| 成人国产精品免费视频| 91地址最新发布| 国产精品色午夜在线观看| 亚洲精品黄网在线观看| 欧美性猛xxx| 久久色精品视频| 亚洲男子天堂网| 日韩精品免费观看| 精品久久久久久久久久国产| 欧美日韩亚洲国产一区| 欧美一区二三区| 日韩av网站在线| www高清在线视频日韩欧美| 亚洲free性xxxx护士白浆| 精品毛片三在线观看| 欧美成人免费视频| 亚洲欧洲日本专区| 91精品视频观看| 亚洲成人a级网| 韩国视频理论视频久久| 久久婷婷国产麻豆91天堂| 日韩av影片在线观看| 人人爽久久涩噜噜噜网站| 在线日韩日本国产亚洲| 国产日韩综合一区二区性色av| 啪一啪鲁一鲁2019在线视频| 亚洲天堂成人在线视频| 欧美大片大片在线播放| 91成人在线观看国产| 日本精品视频在线观看| 国产成人亚洲综合91| 国产在线一区二区三区| 懂色av中文一区二区三区天美| 亚洲女人初尝黑人巨大| 久久久久久91香蕉国产| 91免费国产视频| 亚洲视频免费一区| 精品在线小视频| 欧美成人在线免费| 久久免费国产精品1| 97人洗澡人人免费公开视频碰碰碰| 另类天堂视频在线观看| 亚洲国产精品嫩草影院久久| 欧美成人性生活| 美女视频黄免费的亚洲男人天堂| 欧美影院在线播放| 欧美人与性动交| 欧美精品在线视频观看| 久久精品中文字幕一区| 国产亚洲一区二区在线| 性欧美在线看片a免费观看| 国产91对白在线播放| 国产91精品久久久| 国产精品va在线| 国产一区香蕉久久| 欧美午夜丰满在线18影院| 91久久在线视频| 欧美日韩一区二区在线播放| 欧美性视频精品| 91精品国产综合久久男男| 91免费高清视频| 国产精品电影在线观看| 日韩av成人在线| 久久久久久久久久久国产| 亚洲性生活视频在线观看| 国产精品久久久久久久一区探花| 国产盗摄xxxx视频xxx69| 国产精品成人aaaaa网站| 国产精品狠色婷| 亚洲第一天堂无码专区| 日本不卡免费高清视频| 国产精品美女久久久久av超清| 亚洲人成在线电影| 日韩性生活视频| 久久99久久久久久久噜噜| 精品日本美女福利在线观看| 国产主播精品在线| 国产日韩亚洲欧美| 最近2019中文字幕mv免费看| 久久久人成影片一区二区三区| 日韩视频免费在线| 欧美黑人性生活视频| 欧美影院久久久| 欧美一级视频一区二区| 亚洲无线码在线一区观看| 91久久国产精品| 成人a级免费视频| 久久久久久国产三级电影| 欧美中文字幕第一页| 欧美人与性动交a欧美精品| 国产精品久久久久久av下载红粉| 68精品久久久久久欧美| 国产亚洲精品久久久| 亚洲成年人在线播放| 国产中文字幕日韩| 成人免费在线网址| 久久久久久久香蕉网| 欧美精品videos另类日本| 日日骚久久av| 国产精品久久久久久久久久东京| 亚洲无限乱码一二三四麻| 亚洲欧美日韩另类| 日韩高清中文字幕| 日韩av一区二区在线| 欧美专区中文字幕| www亚洲精品| 欧美大片免费观看在线观看网站推荐| 欧美电影在线观看| 欧美日韩免费在线观看| 欧美性理论片在线观看片免费| 亚洲精品欧美极品| 久久99视频精品| 欧美中文字幕视频| 国产精品一区二区三区免费视频| 91精品国产综合久久香蕉的用户体验| 欧美视频免费在线观看| 亚洲精品按摩视频| 亚洲欧美国产制服动漫| 亚洲欧美日韩图片| 欧美视频专区一二在线观看| 国产福利视频一区二区| 亚洲天堂成人在线视频| 国产精品88a∨| 精品国产福利在线| 欧美成人精品一区| 日韩av网址在线| 91精品国产91久久久久久不卡| 亚洲欧美国产视频| 欧美性猛交xxxx久久久| 国产精品欧美日韩一区二区| 日本欧美国产在线| 精品福利视频导航| 国产精品福利在线观看网址| 国产亚洲欧洲黄色| 综合激情国产一区| 国产免费观看久久黄| 夜夜嗨av一区二区三区免费区| 亚洲精品影视在线观看| 欧美成人性色生活仑片| 国产成人精品在线视频| 亚洲欧美中文日韩在线v日本| 亚洲xxxxx| 亚洲国产成人精品电影| 亚洲欧美成人一区二区在线电影| 成人免费激情视频| 亚洲日韩中文字幕| 欧美日韩成人网| 欧美高跟鞋交xxxxxhd|