前端模塊化的四種規(guī)范

前言:前端模塊化出現(xiàn)的緣由和實(shí)現(xiàn)的一些弊端

出現(xiàn)的緣由

為什么會(huì)出現(xiàn)前端模塊化呢梭灿,要想實(shí)現(xiàn)功能的復(fù)用蟀架,就需要把代碼引入重復(fù)利用重挑,如果不使用模塊化讼呢,我們之前會(huì)使用的方法有哪些呢?
1.直接定義全局function的方式睡扬,那么會(huì)出現(xiàn)函數(shù)命名污染的情況盟蚣,并且各個(gè)部分之間的關(guān)系也看不出來。
2.在命名空間(name space)中定義方法卖怜,定義一個(gè)obj = {function1() {},function2(){}};這樣有個(gè)問題就是函數(shù)內(nèi)部的成員可以被隨意修改屎开,很不安全。
3.通過IIFE模式马靠,也就是函數(shù)自調(diào)用閉包的方式奄抽,暴露給window,但是如果存在模塊之間的依賴甩鳄,就會(huì)很麻煩逞度。
4.IIFE增強(qiáng)模式:引入依賴。為了解決上面的問題娩贷,就出現(xiàn)了IIFE增強(qiáng)模式第晰,說白了就是傳參把其他的模塊給傳進(jìn)去锁孟,就出現(xiàn)了先后順序很重要的問題彬祖,如果前面的都還沒掛載到window上面,此時(shí)運(yùn)行后面的js代碼肯定就是undefined品抽。
因此储笑,為了解決1.命名污染。2.提升代碼的維護(hù)性圆恤。3.更好的分離代碼突倍,實(shí)現(xiàn)按需加載。4提高代碼的復(fù)用性等,我們需要采用模塊化規(guī)范羽历,這里就介紹比較常用的四種模塊化的規(guī)范焊虏,分別是commonJS,AMD,CMD和ES6四種秕磷。

一诵闭、commonJS

1.commonJS-node

node.js原生就支持commonJS的規(guī)范,所以在node.js中可以直接使用澎嚣,不需要引入其他的包了疏尿。commonJS是在服務(wù)端跑的,所以都是讀的本地磁盤中的內(nèi)容易桃,不存在異步的問題褥琐,所以require過來就直接可以用,因?yàn)槭峭降奈钪#詴?huì)有阻塞的情況敌呈,但是在瀏覽器端,一般這些js文件也就是模塊贩汉,很多是通過網(wǎng)絡(luò)請(qǐng)求過來的驱富,是異步的所以使用commonJS就不是那么合適。
語法就是exports和require兩個(gè)匹舞。

1.1exports可以一起導(dǎo)出褐鸥,也可以分開導(dǎo)出,require直接導(dǎo)入

module1.png

上面是module1內(nèi)部的代碼赐稽,可以module.exports = {}的方式叫榕,exports就是一個(gè)對(duì)象


module2.png

上面是module2的內(nèi)部代碼,exports對(duì)象也可以是一個(gè)方法

module3.png

上面是module3的內(nèi)部代碼姊舵,通過exports.foo和exports.bar的方式分開添加

app.png

上面是app.js的內(nèi)部代碼晰绎,可以看到直接通過require('路徑')的方式把模塊直接給引入過來了,非常方便

1.2 關(guān)于package.json

package.png

package.json是通過npm.init初始化的時(shí)候就產(chǎn)生的記錄本包的詳細(xì)信息的文件括丁,包含了name(這個(gè)name不能包含中文荞下,也不能有大寫,在老版本的npm的時(shí)候史飞,不具有自動(dòng)轉(zhuǎn)小寫的功能)尖昏,version以及author等內(nèi)容,并且通過npm install uniq -save(運(yùn)行時(shí)依賴构资,這里的save在npm5之后抽诉,不加save也默認(rèn)就是save)或者npm install uniq --save-dev(開發(fā)時(shí)依賴),在dependencies中記錄

1.3 執(zhí)行app.js

因?yàn)槭窃趎ode環(huán)境中執(zhí)行吐绵,當(dāng)前webStorm執(zhí)行也是用的node迹淌,不是在瀏覽器環(huán)境中河绽,無論通過node app.js還是右鍵執(zhí)行app.js都可以完成。

1.4 commonJS的不足

既然commonJS已經(jīng)這么方便了唉窃,為啥會(huì)出現(xiàn)AMD和CMD以及ES6的后續(xù)的規(guī)范呢耙饰,就是因?yàn)閏ommonJS是在node中實(shí)現(xiàn)的,也就是node環(huán)境中可以支持require和exports纹份,但是在瀏覽器環(huán)境中榔幸,是不支持的,所以要想在瀏覽器端使用commonJS的規(guī)范的話矮嫉,就必須使用browserify這種第三方包把代碼給轉(zhuǎn)換成瀏覽器端支持的代碼削咆,后面將寫commonJS在瀏覽器端的實(shí)現(xiàn)。

2.commonJS-Browserify

由于前文中提到的commonJS規(guī)范在瀏覽器端無法適用的情況蠢笋,我們需要引入一個(gè)第三方包也就是Browserify拨齐,把原本只能在node環(huán)境中跑的代碼給轉(zhuǎn)換成瀏覽器端可以使用的代碼。
browserify的安裝(必須全局和局部都安裝):
①昨寞、全局安裝
npm install browserify -g
②瞻惋、局部安裝
npm install broserify --save-dev
安裝完成之后,運(yùn)行browserify js/src/app.js -o js/dist/bundle.js


browserify.png

上述指令中的-o援岩,代表的是output歼狼,后面js/dist/bundle.js就是輸出的目標(biāo)位置,沒有dist目錄的話會(huì)自動(dòng)創(chuàng)建享怀,而且這個(gè)命令運(yùn)行之后羽峰,命令行不會(huì)有什么打印,不代表沒執(zhí)行成功添瓷。(這里其他module1梅屉,module2這些都沒有變,和前面1當(dāng)中的代碼是一樣的鳞贷,只是在瀏覽器中執(zhí)行了)


script標(biāo)簽引入.png

在html中通過script標(biāo)簽引入那個(gè)bundle.js就可以了坯汤,接下來在瀏覽器中執(zhí)行。
瀏覽器中執(zhí)行結(jié)果.png

上圖就是在瀏覽器環(huán)境中執(zhí)行的結(jié)果搀愧,如果script的標(biāo)簽src引入的不是這個(gè)bundle惰聂,直接是app.js的話,require這種語法咱筛,瀏覽器根本就不認(rèn)識(shí)搓幌,就會(huì)出現(xiàn)下面的這個(gè)情況。
不用browserify打包.png

二眷蚓、AMD規(guī)范

AMD(Asynchronous Module Definition異步模塊定義)規(guī)范相比于CMD來說應(yīng)用得更加廣泛一些鼻种。AMD是專門用于瀏覽器端的反番,模塊的加載是異步的沙热。
AMD規(guī)范是通過Require.js實(shí)現(xiàn)的叉钥,所以需要下載Require.js文件。
基本語法:
①篙贸、定義暴露模塊:如果是定義沒有依賴的模塊
define(function(){
return 模塊
})
如果是定義有依賴的模塊
define(['module1','module2'],function(module1,module2) {
return 模塊
})
②投队、引入使用模塊
requirejs(['module1','module2'],function(m1,m2) {
使用m1/m2
})

2.1沒有AMD時(shí)候的模塊化實(shí)現(xiàn)方式

alert .png
dataService.png
app.png
html.png

如上圖所示,在js文件夾中創(chuàng)建了alert和dataService兩個(gè)模塊爵川,這些模塊之間都是通過IIFE也就是立即執(zhí)行函數(shù)來把模塊內(nèi)的方法暴露給window對(duì)象的敷鸦,三者之間存在依賴關(guān)系,必須按照先后順序加入script標(biāo)簽寝贡,先dataService扒披,后alert再app.js這三個(gè)加載順序,這就是沒有AMD的時(shí)候的執(zhí)行方法圃泡,就是暴露給window碟案,但這樣的缺陷是非常明顯的,就是模塊之間的依賴必須要手動(dòng)去定好颇蜡,不然一定會(huì)存在undefined的情況价说。

2.2 采用AMD-RequireJS的方式實(shí)現(xiàn)模塊化

html.png

上圖是使用require.js來實(shí)現(xiàn)的方式,就是script標(biāo)簽的scr是require.js风秤,但是有一個(gè)主js的入口鳖目,就是data-main屬性,里面指定了主文件的入口缤弦。


main.png

上圖就是main.js的代碼领迈。里面是一個(gè)立即執(zhí)行函數(shù),因?yàn)樗恍枰傧蛲獗┞督涌诎澹苯泳褪褂胷equirejs方法惦费,把需要的模塊名字傳入,然后后面回調(diào)函數(shù)進(jìn)行使用就可以了抢韭。


alerter.png

上面是alerter薪贫,他引入了dataService模塊和jquery(必須小寫)模塊,回調(diào)函數(shù)中刻恭,就使用了其他的模塊瞧省。
dataService.png

這個(gè)dataService,是不需要依賴其他模塊的鳍贾,所以沒有傳前面的數(shù)組鞍匾,直接定義好,然后暴露接口就可以了骑科。
層級(jí)目錄.png

上面是層級(jí)目錄橡淑,記得libs下面有這個(gè)require.js


requirejs配置.png

這個(gè)部分就是requirejs的配置,必須配置咆爽,否則根本不知道你數(shù)組里頭引入梁棠,或者定義的時(shí)候置森,那個(gè)模塊到底是誰,后面映射了路徑符糊。shim用來解決那些不支持AMD規(guī)范的js包的凫海,就比如angular,本來就是不支持的男娄,你配置了path也沒用行贪,配置shim就可以了,上面也可以配置baseUrl模闲。

三建瘫、CMD規(guī)范

CMD規(guī)范用的相對(duì)少一些,是阿里開發(fā)的尸折,但現(xiàn)在賣給外國人了暖混,使用起來的語法有點(diǎn)像CommonJS和AMD的結(jié)合版,SeaJS實(shí)現(xiàn)了CMD規(guī)范翁授,所以需要下載這個(gè)seajs拣播。
使用語法:
①、定義沒有依賴的模塊
define(function(require,exports,module) {
exports.xxx = value;
module.exports = value;
//這個(gè)和commonJS很像收擦,關(guān)鍵就是那個(gè)exports對(duì)象
})
②贮配、定義有依賴的模塊
define(function(require,exports,module) {
var module2 = require('./module2');
require.async('./module3',function(m3) {
///使用module3,是異步的塞赂,到時(shí)候module3拿到了就給回調(diào)直接執(zhí)行
})
exports.xxx = value
})
③泪勒、引入使用模塊
define(function(require) {
var m1 = require('./module1')
var m4 = require('./module4')
//執(zhí)行...
})


html.png

上圖是html里面的使用方法,先引入sea.js宴猾,然后seajs.use一下main.js圆存。


mainjs.png

main.js里面因?yàn)橹皇窃谑褂茫圆恍枰雍竺娴膃xports和module仇哆,當(dāng)然你開心也可以加上沦辙。
里面的引入方式,還是一樣的讹剔,就是require就可以了油讯,很像commonjs。
module1.png

上面是module1延欠,接下來以此就是四個(gè)module陌兑。
module2.png
module3.png

上面是module3和2,都是一個(gè)沒有依賴的由捎。


module4.png

上面是module4兔综,依賴了2和3。前面mainjs引入了module1和4,執(zhí)行后發(fā)現(xiàn)異步調(diào)用的3被放在后面了软驰,說明確實(shí)異步了涧窒,結(jié)果就是1243。


7575.png

上面是seajs的位置碌宴,不要忘記。
對(duì)比CMD和AMD可以發(fā)現(xiàn)蒙畴,AMD的依賴是前置的贰镣,在一個(gè)數(shù)組里頭,直接就先加載了再執(zhí)行后面的代碼膳凝,而CMD的依賴是后置的碑隆,只有需要的時(shí)候,才會(huì)去執(zhí)行模塊的加載蹬音。

四上煤、ES6

ES6需要安裝一些加載插件:babel-cli,babel-preset-es2015和browserify,babel-cli主要是實(shí)現(xiàn)命令行著淆,執(zhí)行babel指令可以運(yùn)行劫狠,后面那個(gè)babel-preset-es2015才是把ES6轉(zhuǎn)成ES5的工具,babel不僅可以完成es6轉(zhuǎn)es5永部,還能轉(zhuǎn)其他的独泞,轉(zhuǎn)啥就下載啥,所以這里就需要下載這個(gè)babel-preset-es2015苔埋。
1.npm install babel-cli browserify -g
全局安裝babel-cli這樣我們?cè)谌魏蔚胤蕉伎梢詧?zhí)行babel命令了懦砂,browserify我們前面已經(jīng)安裝過了,現(xiàn)在也安裝一下吧组橄,反正也不吃虧荞膘。
2.npm install babel-preset-es2015 --save-dev
這個(gè)很明顯是開發(fā)時(shí)候的依賴,轉(zhuǎn)了到時(shí)候運(yùn)行的時(shí)候就不需要再轉(zhuǎn)了嘛玉工。
3.定義.babelrc
不要忘記前面那個(gè). (點(diǎn))羽资,在根目錄里面新建一個(gè).babelrc,加了點(diǎn)的時(shí)候,webstorm自動(dòng)把它識(shí)別為json文件了遵班。babelrc也能在package.json里面配置
{
"name":'pname',
"babel": {
//config
}
}


配置babelrc.png

我們這里直接在根目錄配置babelrc,rc代表的是run control運(yùn)行控制削罩。
4.編寫模塊之間的依賴
5.編譯
因?yàn)榍懊鎸懙膉s文件,首先瀏覽器根本就不認(rèn)識(shí)ES6的語法费奸,因此需要babel來轉(zhuǎn)成es5弥激,另外,需要把它弄到瀏覽器環(huán)境中能執(zhí)行愿阐,所以必須browserify
5.1微服、babel js/src -d js/lib
-d就是目標(biāo)是js/lib文件夾
-d前面就是需要編譯的整個(gè)文件夾路徑,里頭都需要編譯


babel命令.png

5.2 browserify js/lib/main.js -o js/dist/bundle.js
這個(gè)就是把他弄到服務(wù)器端跑的工具
上面兩兩步編譯之后缨历,瀏覽器就能夠識(shí)別并運(yùn)行了以蕴。


成功1.png
成功2.png

6.默認(rèn)暴露的寫法(補(bǔ)充)

默認(rèn)暴露的module3.png

成功3.png

1.值得注意的一點(diǎn):package.json中name的值糙麦,不要取跟github上常用包一樣的名字,否則會(huì)死活無法下載下來丛肮。
2.安裝babel必須安裝babel-cli赡磅,cli就是command line interface也就是命令行接口,比如node里面的npm為啥可以執(zhí)行宝与,是因?yàn)槔锩婢陀衏li焚廊,存了各種命令,但是babel自身沒有习劫,所以需要手動(dòng)下載咆瘟。
3.npm install jquery@1指定下載jquery1里面的最新版本,默認(rèn)包就是import $ from 'jquery'不需要加路徑名诽里,而且也是默認(rèn)暴露的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末袒餐,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子谤狡,更是在濱河造成了極大的恐慌灸眼,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件墓懂,死亡現(xiàn)場(chǎng)離奇詭異幢炸,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)拒贱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門宛徊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人逻澳,你說我怎么就攤上這事闸天。” “怎么了斜做?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵苞氮,是天一觀的道長。 經(jīng)常有香客問我瓤逼,道長笼吟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任霸旗,我火速辦了婚禮贷帮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘诱告。我一直安慰自己撵枢,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著锄禽,像睡著了一般潜必。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上沃但,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天磁滚,我揣著相機(jī)與錄音,去河邊找鬼宵晚。 笑死垂攘,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的坝疼。 我是一名探鬼主播搜贤,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼谆沃,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼钝凶!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起唁影,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤耕陷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后据沈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體哟沫,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年锌介,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了嗜诀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡孔祸,死狀恐怖隆敢,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情崔慧,我是刑警寧澤拂蝎,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站惶室,受9級(jí)特大地震影響温自,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜皇钞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一悼泌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧夹界,春花似錦券躁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽撒桨。三九已至搬俊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蕴轨。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留抛虫,地道東北人懂缕。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像键俱,于是被迫代替她去往敵國和親兰绣。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355