国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

前端模塊及依賴管理的新選擇:Browserify

evin2016 / 1032人閱讀

摘要:它的關(guān)鍵能力,是模塊及依賴管理。其次,保持局部變量風(fēng)格。我們很習(xí)慣通過(guò)和這樣的全局變量來(lái)訪問(wèn)這樣的庫(kù),但如果使用,它們都應(yīng)只作為局部變量這里的就只存在于這個(gè)文件的代碼范圍內(nèi)獨(dú)立的作用域。

引言 1. manually

以前,我新開(kāi)一個(gè)網(wǎng)頁(yè)項(xiàng)目,然后想到要用jQuery,我會(huì)打開(kāi)瀏覽器,然后找到j(luò)Query的官方網(wǎng)站,點(diǎn)擊那個(gè)醒目的“Download jQuery”按鈕,下載到.js文件,然后把它丟在項(xiàng)目目錄里。在需要用到它的地方,這樣用 2. Bower

后來(lái),我開(kāi)始用[Bower][]這樣的包管理工具。所以這個(gè)過(guò)程變成了:先打開(kāi)命令行用bower安裝jQuery。

bower install jquery

再繼續(xù)用 3. npm&Browserify

現(xiàn)在,我又有了新的選擇,大概是這樣:

命令行用npm安裝jQuery。

npm install jquery

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

var $ = require("jquery");

沒(méi)錯(cuò),這就是使用npm的包的一般方法。但特別的是,這個(gè)npm的包是我們熟知的jquery,而它將用在瀏覽器中。

[Browserify][],正如其名字所體現(xiàn)的動(dòng)作那樣,讓原本屬于服務(wù)器端的Node及npm,在瀏覽器端也可使用。

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

browserify main.js -o bundle.js

最后,用

這就是依托Browserify建立起來(lái)的第三選擇。

等下,怎么比以前變復(fù)雜了?

CommonJS風(fēng)格的模塊及依賴管理

其實(shí),在這個(gè)看起來(lái)更復(fù)雜的過(guò)程中,require()具有非凡的意義。

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

就模塊及依賴管理這個(gè)問(wèn)題而言,已經(jīng)有RequireJS[]這些優(yōu)秀的作品。而現(xiàn)在,Browserify又給了我們新的選擇。

Browserify參照了Node中的模塊系統(tǒng),約定用require()來(lái)引入其他模塊,用module.exports來(lái)引出模塊。在我看來(lái),Browserify不同于RequireJS和Sea.js的地方在于,它沒(méi)有著力去提供一個(gè)“運(yùn)行時(shí)”的模塊加載器,而是強(qiáng)調(diào)進(jìn)行預(yù)編譯。預(yù)編譯會(huì)帶來(lái)一個(gè)額外的過(guò)程,但對(duì)應(yīng)的,你也不再需要遵循一定規(guī)則去加一層包裹。因此,相比較而言,Browserify提供的組織方式更簡(jiǎn)潔,也更符合CommonJS規(guī)范。

像寫(xiě)Node那樣去組織你的JavaScript,Browserify會(huì)讓它們?cè)跒g覽器里正常運(yùn)行的。

安裝及使用 命令行形式

命令行形式是官方貼出來(lái)的用法,因?yàn)榭雌饋?lái)最簡(jiǎn)單。

Browserify本身也是npm,通過(guò)npm的方式安裝:

npm install -g browserify

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

browserify entry.js -o bundle.js

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


有關(guān)這個(gè)編譯命令的配置參數(shù),請(qǐng)參照[node-browserify#usage][]。如果你想要做比較精細(xì)的配置,命令行形式可能會(huì)不太方便。這種時(shí)候,推薦結(jié)合Gulp使用。

+ Gulp形式

結(jié)合Gulp使用時(shí),你的Browserify只安裝在某個(gè)項(xiàng)目?jī)?nèi):

npm install browserify --save-dev

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

接下來(lái)是gulpfile.js的部分,下面是一個(gè)簡(jiǎn)單示例:

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是獨(dú)立的,我們需要直接使用它的API,并將它加入到Gulp的任務(wù)中。

在上面的代碼中,debug: true是告知Browserify在運(yùn)行同時(shí)生成內(nèi)聯(lián)sourcemap用于調(diào)試。引入gulp-sourcemaps并設(shè)置loadMaps: true是為了讀取上一步得到的內(nèi)聯(lián)sourcemap,并將其轉(zhuǎn)寫(xiě)為一個(gè)多帶帶的sourcemap文件。vinyl-source-stream用于將Browserify的bundle()的輸出轉(zhuǎn)換為Gulp可用的[vinyl][](一種虛擬文件格式)流。vinyl-buffer用于將vinyl流轉(zhuǎn)化為buffered vinyl文件(gulp-sourcemaps及大部分Gulp插件都需要這種格式)。

這樣配置好之后,直接運(yùn)行gulp browserify就可以得到結(jié)果了,可能像這樣:

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

有關(guān)更多Browserify + Gulp的示例,請(qǐng)參考[Gulp Recipes][]。

特性及簡(jiǎn)要原理

使用Browserify來(lái)組織JavaScript,有什么要注意的地方嗎?

要回答這個(gè)問(wèn)題,我們先看看Browserify到底做了什么。下面是一個(gè)比較詳細(xì)的例子。

項(xiàng)目?jī)?nèi)現(xiàn)在用到2個(gè).js文件,它們存在依賴關(guān)系,其內(nèi)容分別是:

name.js

module.exports = "aya";

main.js

var name = require("./name");

console.log("Hello! " + name);

然后對(duì)main.js運(yùn)行Browserify,得到的bundle.js的文件內(nèi)容是這樣的:

(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

請(qǐng)先忽略掉省略號(hào)里的部分。然后,它的結(jié)構(gòu)就清晰多了。可以看到,整體是一個(gè)立即執(zhí)行的函數(shù)([IIFE][]),該函數(shù)接收了3個(gè)參數(shù)。其中第1個(gè)參數(shù)比較復(fù)雜,第2、3個(gè)參數(shù)在這里分別是{}[1]

模塊map

第1個(gè)參數(shù)是一個(gè)Object,它的每一個(gè)key都是數(shù)字,作為模塊的id,每一個(gè)數(shù)字key對(duì)應(yīng)的值是長(zhǎng)度為2的數(shù)組。可以看出,前面的main.js中的代碼,被function(require, module, exports){}這樣的結(jié)構(gòu)包裝了起來(lái),然后作為了key1數(shù)組里的第一個(gè)元素。類似的,name.js中的代碼,也被包裝,對(duì)應(yīng)到key2

數(shù)組的第2個(gè)元素,是另一個(gè)map對(duì)應(yīng),它表示的是模塊的依賴。main.js在key1,它依賴name.js,所以它的數(shù)組的第二個(gè)元素是{"./name": 2}。而在key2name.js,它沒(méi)有依賴,因此其數(shù)組第二個(gè)元素是空Object{}

因此,這第1個(gè)復(fù)雜的參數(shù),攜帶了所有模塊的源碼及其依賴關(guān)系,所以叫做模塊map。

包裝

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

因?yàn)椋瑸g覽器原生環(huán)境中,并沒(méi)有require()。所以,需要用代碼去實(shí)現(xiàn)它(RequireJS和Sea.js也做了這件事)。這個(gè)包裝函數(shù)提供的3個(gè)參數(shù),requiremoduleexports,正是由Browserify實(shí)現(xiàn)了特定功能的3個(gè)關(guān)鍵字。

緩存

第2個(gè)參數(shù)幾乎總是空的{}。它如果有的話,也是一個(gè)模塊map,表示本次編譯之前被加載進(jìn)來(lái)的來(lái)自于其他地方的內(nèi)容。現(xiàn)階段,讓我們忽略它吧。

入口模塊

第3個(gè)參數(shù)是一個(gè)數(shù)組,指定的是作為入口的模塊id。前面的例子中,main.js是入口模塊,它的id是1,所以這里的數(shù)組就是[1]。數(shù)組說(shuō)明其實(shí)還可以有多個(gè)入口,比如運(yùn)行多個(gè)測(cè)試用例的場(chǎng)景,但相對(duì)來(lái)說(shuō),多入口的情況還是比較少的。

實(shí)現(xiàn)功能

還記得前面忽略掉的省略號(hào)里的代碼嗎?這部分代碼將解析前面所說(shuō)的3個(gè)參數(shù),然后讓一切運(yùn)行起來(lái)。這段代碼是一個(gè)函數(shù),來(lái)自于browser-pack項(xiàng)目的[prelude.js][]。令人意外的是,它并不復(fù)雜,而且寫(xiě)有豐富的注釋,很推薦你自行閱讀。

所以,到底要注意什么?

到這里,你已經(jīng)看過(guò)了Browserify是如何工作的。是時(shí)候回到前面的問(wèn)題了。首先,在每個(gè)文件內(nèi),不再需要自行包裝

你可能已經(jīng)很習(xí)慣類似下面這樣的寫(xiě)法:

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

但你已經(jīng)了解到,Browserify的編譯會(huì)將你的代碼封裝在局部作用域內(nèi),所以,你不再需要自己做這個(gè)事情,像這樣會(huì)更好:

// Your code here.

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

其次,保持局部變量風(fēng)格。我們很習(xí)慣通過(guò)window.jQuerywindow.$這樣的全局變量來(lái)訪問(wèn)jQuery這樣的庫(kù),但如果使用Browserify,它們都應(yīng)只作為局部變量:

var $ = require("jquery");

$("#alice").text("Hello!");

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

然而,新的問(wèn)題又來(lái)了,既然jQuery變成了這種局部變量的形式,那我們熟悉的各種jQuery插件要如何使用呢?

browserify-shim

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




很多jQuery插件是這樣做的:默認(rèn)window.jQuery存在,然后取這個(gè)全局變量,把自己添加到j(luò)Query中。顯然,這在Browserify的組織方式里是沒(méi)法用的。

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

下面,以jQuery插件[jquery.pep.js][]為例,請(qǐng)看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();

完成!到此,經(jīng)過(guò)Browserify編譯后,將可以正常運(yùn)行這個(gè)jQuery插件。

這是一個(gè)怎樣的過(guò)程呢?

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

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

可以看出,它默認(rèn)當(dāng)前環(huán)境中已存在一個(gè)變量jQuery(如果不存在,則報(bào)錯(cuò))。package.json中的"depends": ["jquery:jQuery"] 是為它添加依賴聲明,前一個(gè)jquery表示require("jquery"),后一個(gè)jQuery則表示將其命名為jQuery(賦值語(yǔ)句)。這樣,插件代碼運(yùn)行的時(shí)候就可以正常找到jQuery變量,然后將它自己添加到j(luò)Query中。

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

關(guān)于配置的更多說(shuō)明,請(qǐng)參照browserify-shim官方文檔[]。此外,如果你覺(jué)得browserify-shim有些難以理解或者對(duì)它的原理也有興趣,推薦閱讀[這篇Stack Overflow上的回答][]。

當(dāng)然,對(duì)于已經(jīng)處理了CommonJS兼容的庫(kù)或插件(比如已經(jīng)發(fā)布到npm),browserify-shim是不需要的。

其實(shí)還有的更多transform

在前面browserify-shim的例子中,"browserify": {"transform": [ "browserify-shim" ]}其實(shí)是Browserify的配置。可以看出,browserify-shim只是Browserify的其中一種transform。在它之外,還有[很多的transform][]可用,分別應(yīng)對(duì)不同的需求,使Browserify的體系更為完善。

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

一點(diǎn)提示

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

var lang = "zh_cn";
var i18n = require("./" + lang);
文檔資料

有關(guān)Browserify更詳細(xì)的說(shuō)明文檔,請(qǐng)看[browserify-handbook][]。

結(jié)語(yǔ)

我覺(jué)得Browserify很有趣,它用了這樣一個(gè)名字,讓你覺(jué)得它好像只是一個(gè)Node的瀏覽器端轉(zhuǎn)化工具。為此,它還完成了Node中大部分核心庫(kù)的瀏覽器端實(shí)現(xiàn)。但實(shí)際上,它走到了更遠(yuǎn)的地方,并在JavaScript模塊化開(kāi)發(fā)這個(gè)重要的領(lǐng)域中,創(chuàng)立了一個(gè)全新的體系。

喜歡CommonJS的簡(jiǎn)潔風(fēng)格?請(qǐng)嘗試Browserify!

(重新編輯自我的博客,原文地址:http://acgtofe.com/posts/2015/06/modular-javascript-with-browserify)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/85773.html

相關(guān)文章

  • JS學(xué)習(xí)筆記 - 模塊

    摘要:在開(kāi)發(fā)大型的項(xiàng)目中,可能會(huì)使用到管理的模塊化工具。說(shuō)道,學(xué)習(xí)過(guò)的同學(xué)會(huì)比較熟悉,是服務(wù)器模塊的規(guī)范,采用了這個(gè)規(guī)范。可能是未來(lái)模塊化解決方案的首選。 本文章記錄本人在學(xué)習(xí) JavaScript 中理解到的一些東西,加深記憶和并且整理記錄下來(lái),方便之后的復(fù)習(xí)。 在開(kāi)發(fā)大型的web項(xiàng)目中,可能會(huì)使用到管理js的模塊化工具。但是在前端輪子漫天飛的時(shí)代。那一款js模塊化工具真正適合我...

    CntChen 評(píng)論0 收藏0
  • Javascript模塊webpack基本介紹

    摘要:可維護(hù)性根據(jù)定義,每個(gè)模塊都是獨(dú)立的。良好設(shè)計(jì)的模塊會(huì)盡量與外部的代碼撇清關(guān)系,以便于獨(dú)立對(duì)其進(jìn)行改進(jìn)和維護(hù)。這標(biāo)志模塊化編程正式誕生。的模塊系統(tǒng),就是參照規(guī)范實(shí)現(xiàn)的。對(duì)象就代表模塊本身。 javascript模塊化及webpack基本介紹 JavaScript 模塊化發(fā)展歷程 什么是模塊化 ? 為什么要做Javascript模塊化? JavaScript 模塊化發(fā)展歷程 什么是模...

    figofuture 評(píng)論0 收藏0
  • 前端工具演變

    摘要:做菜的工具有歷史演變的過(guò)程,我們軟件開(kāi)發(fā)的工具也是如此。今天就從前端工具演變來(lái)聊聊前端的歷史發(fā)展。上面的做法很顯然是存在效率和不方便的問(wèn)題,在這種情況下前端的工具應(yīng)運(yùn)而生。是只被用于管理前端的組件,例如,,的工具,只用在前端。 假如你烘焙過(guò)蛋糕(哪怕沒(méi)有親自做過(guò),但是也應(yīng)該聽(tīng)說(shuō)過(guò)),除了基本的面粉,雞蛋等原材料外,或許你還需要一個(gè)電動(dòng)蛋白打發(fā)器,一個(gè)烤箱。這是現(xiàn)代的做法,那么在打發(fā)器和...

    icyfire 評(píng)論0 收藏0
  • 基于 Gulp + Browserify 構(gòu)建 ES6 環(huán)境下的自動(dòng)化前端項(xiàng)目

    摘要:本文特此給大家介紹下如何使用配合來(lái)構(gòu)建基于的前端項(xiàng)目。最后,在目錄下會(huì)生成最終的項(xiàng)目文件。執(zhí)行單元測(cè)試本例中使用進(jìn)行單元測(cè)試。 隨著React、Angular2、Redux等前沿的前端框架越來(lái)越流行,使用webpack、gulp等工具構(gòu)建前端自動(dòng)化項(xiàng)目也隨之變得越來(lái)越重要。鑒于目前業(yè)界普遍更流行使用webpack來(lái)構(gòu)建es6(ECMAScript 2015)前端項(xiàng)目,網(wǎng)上的相關(guān)教程也比...

    yuanxin 評(píng)論0 收藏0
  • Laravel學(xué)習(xí)筆記三-前端工作流

    摘要:本節(jié)將學(xué)習(xí)是如何利用形成一套完整的前端工作流模式的。你也可以使用下面命令來(lái)強(qiáng)制安裝所有模塊,不管該模塊之前是否安裝過(guò)由于國(guó)內(nèi)墻的原因,使用安裝會(huì)非常緩慢,慢到想切,不過(guò)還好,我們可以使用淘寶提供的國(guó)內(nèi)鏡像進(jìn)行下載。 本節(jié)將學(xué)習(xí) Laravel 是如何利用 Sass, NPM, Gulp形成一套完整的前端工作流模式的。 一、句法強(qiáng)大的樣式表Sass Sass 是一種可用于編寫(xiě)CSS的語(yǔ)言...

    liuchengxu 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<