網(wǎng)站前端模塊化開(kāi)發(fā)策略研究
引言
當(dāng)今互聯(lián)網(wǎng)飛速發(fā)展,網(wǎng)絡(luò)用戶的需求變化既快又大,且不可捉摸,大部分網(wǎng)站的更新周期都是以日、小時(shí)甚至分鐘為單位。在這種情況下,網(wǎng)站的前端就成了 變化最頻繁的部分。隨著互聯(lián)網(wǎng)公司對(duì)前端開(kāi)發(fā)的逐漸重視,前端開(kāi)發(fā)人數(shù)也越來(lái)越多,可是,技術(shù)人員的投入總是有限的。面對(duì)需求的快速變化,引發(fā)了很多如前 端編碼規(guī)范、前端性能優(yōu)化、前端安全漏洞防范等方面的問(wèn)題。為了解決這些問(wèn)題,一種具有先進(jìn)開(kāi)發(fā)思想和良好設(shè)計(jì)模式的前端模塊化技術(shù)正逐漸成熟,并受到越來(lái)越多公司的青睞。
1 前端模塊化技術(shù)的應(yīng)用現(xiàn)狀
前端模塊化開(kāi)發(fā)就是將網(wǎng)站的前端按照布局和功能分成若干個(gè)模塊,每個(gè)模塊完成特定的功能[1],然后,將所有模塊按一定組織方式形成一個(gè)整體,完成整 個(gè)系統(tǒng)的功能。這樣就極大地降低了程序員開(kāi)發(fā)時(shí)彼此之間的干擾,更加有利于多人協(xié)同開(kāi)發(fā)。而且,基于前端模塊化開(kāi)發(fā)技術(shù)的應(yīng)用還具有提高網(wǎng)頁(yè)瀏覽速度、高 效組織與維護(hù)網(wǎng)絡(luò)信息資源、減少代碼冗余等優(yōu)點(diǎn)。
為解決前端模塊化開(kāi)發(fā)技術(shù)發(fā)展過(guò)程中遇到的種種問(wèn)題,出現(xiàn)了一些開(kāi)發(fā)工具,如:CSS Sprites、YUI Compressor等。為提高前端模塊化開(kāi)發(fā)效率,又出現(xiàn)了一些javascript組件庫(kù),如 Jquery、Yahoo UI Library、mootools等。這些工具和組件庫(kù)只是在某個(gè)方面彌補(bǔ)了前端模塊化開(kāi)發(fā)的技術(shù)空白并提高了工作效率,卻并不能完全解決問(wèn)題。而且,隨著前端模塊化開(kāi)發(fā)技術(shù)的蓬勃發(fā)展,網(wǎng)站的大量需求又都轉(zhuǎn)到前端處理,甚至將網(wǎng)頁(yè)做成交互型應(yīng)用程序,這個(gè)趨勢(shì)使前端開(kāi)發(fā)代碼量急速增加,并更進(jìn)一步增加了前端模塊化開(kāi)發(fā)的難度。
由此可見(jiàn),現(xiàn)在的前端模塊化開(kāi)發(fā)已經(jīng)發(fā)展成為一個(gè)系統(tǒng)工程,開(kāi)發(fā)人員必須從多方面考慮,多角度分析,從細(xì)節(jié)做起,共同協(xié)作才能實(shí)現(xiàn)前端模塊化開(kāi)發(fā)的目 標(biāo)。目前,國(guó)內(nèi)只有騰訊、百度、新浪、豆瓣等少數(shù)幾個(gè)網(wǎng)站設(shè)計(jì)了自己的前端模塊化開(kāi)發(fā)框架結(jié)構(gòu),擁有自己的開(kāi)發(fā)策略,但這些公司對(duì)于前端模塊化開(kāi)發(fā)技術(shù)的運(yùn)用也不是很嫻熟。因此,對(duì)前端模塊化開(kāi)發(fā)策略的研究還是非常必要的。
2 前端模塊化技術(shù)的開(kāi)發(fā)策略
前端模塊化開(kāi)發(fā)的基本思想與模塊化的程序設(shè)計(jì)相似,即在Web上以模塊為基本單位劃分與組織信息,將網(wǎng)頁(yè)的內(nèi)容分開(kāi),形成若干個(gè)相對(duì)獨(dú)立的模塊。模塊只是用來(lái)存放基本頁(yè)面元素的容器,并把常用的頁(yè)面元素也制成模塊,便于這些頁(yè)面元素的調(diào)用與管理。因此,前端模塊化技術(shù)沒(méi)有復(fù)雜的邏輯運(yùn)算,而是主要關(guān)注 作為骨架的HTML與作為表現(xiàn)層的CSS以及實(shí)現(xiàn)行為的JavaScript三方面的拼裝組合和代碼復(fù)用上,以減少它們之間的循環(huán)依賴、降低耦合、提高設(shè) 計(jì)效率。這時(shí)就需要有一套有效的開(kāi)發(fā)策略,所有的模塊都在這個(gè)策略下進(jìn)行設(shè)計(jì),并以此劃分工作任務(wù)。常見(jiàn)的開(kāi)發(fā)策略有以下三種。
2.1 傳統(tǒng)模塊化開(kāi)發(fā)策略
傳統(tǒng)模塊化開(kāi)發(fā)首先將每個(gè)頁(yè)面拆分成很多個(gè)基本模塊,比如logo、導(dǎo)航、內(nèi)容1、內(nèi)容2、尾部導(dǎo)航、版權(quán)信息等等,然后將每個(gè)模塊生成一個(gè)單獨(dú)的文件。當(dāng)頁(yè)面要求加載時(shí),使用載入CSS,使用Ajax技術(shù)分別載入。
這樣做看上去簡(jiǎn)單易行,卻存在很多問(wèn)題。首先會(huì)出現(xiàn)大量模塊,不但不便于管理,還會(huì)使請(qǐng)求數(shù)猛增。例如一個(gè)頁(yè)面有四個(gè)模塊,那就至少會(huì)產(chǎn)生4(個(gè)模 塊)×2(個(gè)類(lèi)型:CSS/JS)=8個(gè)請(qǐng)求,再加上一些函數(shù)庫(kù),請(qǐng)求就會(huì)更多。另外內(nèi)容未經(jīng)過(guò)壓縮也會(huì)造成嚴(yán)重的性能問(wèn)題,阻塞頁(yè)面顯示。其次,這種方式不適合團(tuán)隊(duì)開(kāi)發(fā)。
2.2 頁(yè)面級(jí)的模塊化開(kāi)發(fā)策略
頁(yè)面級(jí)模塊化開(kāi)發(fā),指根據(jù)不同頁(yè)面的模塊劃分情況設(shè)定所需的JavaScript與CSS模塊。例如頁(yè)面A,設(shè)定header.js、 list.js、info.js、header.css、list.css和info.css六個(gè)模塊,頁(yè)面B設(shè)定info.css和info.js兩個(gè)模塊。所有頁(yè)面和其所依賴的模塊關(guān)系都由開(kāi)發(fā)者寫(xiě)在頁(yè)面級(jí)的設(shè)定文件中。當(dāng)某個(gè)頁(yè)面請(qǐng)求其所需模塊時(shí),通過(guò)一些工具,例如Mini工具,依據(jù)設(shè)定文件將所需模塊合并及最小化,這樣只需一個(gè)請(qǐng)求,就可以得到請(qǐng)求頁(yè)面所需的所有模塊,解決了傳統(tǒng)模塊化開(kāi)發(fā)中請(qǐng)求數(shù)量過(guò)多和內(nèi)容未壓縮的問(wèn)題。
雖然頁(yè)面級(jí)的模塊化開(kāi)發(fā)策略有效地解決了請(qǐng)求數(shù)量及壓縮問(wèn)題,但仍存在很多問(wèn)題。首先,不易維護(hù)。當(dāng)需要移除一個(gè)頁(yè)面時(shí),該頁(yè)面所依賴的模塊也應(yīng)全部移除,可是又不能***確定別的頁(yè)面不會(huì)用到將要移除的依賴模塊,最終導(dǎo)致模塊越積越多。其次,線上調(diào)試非常困難。因?yàn)榘l(fā)布的是混淆后的代碼,幾乎無(wú)法 實(shí)現(xiàn)調(diào)試。因此,還需要通過(guò)進(jìn)一步調(diào)整開(kāi)發(fā)策略來(lái)解決問(wèn)題。
2.3 模塊級(jí)的模塊化開(kāi)發(fā)策略
模塊級(jí)的模塊化開(kāi)發(fā),是指開(kāi)發(fā)人員分別定義自身頁(yè)面模塊的依賴關(guān)系,即每個(gè)頁(yè)面所需模塊的設(shè)定,而不是像頁(yè)面級(jí)模塊化開(kāi)發(fā)那樣記錄在一個(gè)中央設(shè)定文件 中。當(dāng)用戶請(qǐng)求某個(gè)頁(yè)面時(shí),頁(yè)面的Controller會(huì)指定需要載入的頁(yè)面,但不需指定該頁(yè)面要依賴哪些模塊,這些需要載入的模塊會(huì)由加載的 Loader自行計(jì)算得到。然后,Loader會(huì)與服務(wù)器端交互,將所需模塊分組、合并與壓縮,再并行下載到請(qǐng)求下載的瀏覽器上。
當(dāng)前基于這種模塊級(jí)模塊化開(kāi)發(fā)規(guī)范的框架有很多,例如RequireJS和YUI3。RequireJS是目前使用非常廣泛的框架,只要定義好模塊的 依賴關(guān)系,就會(huì)依次將所需模塊自動(dòng)載入,不需做任何配置。而發(fā)布到線上時(shí),可以使用Node.js提供的r.js進(jìn)行合并與最小化。但 是,RequireJS仍然存在發(fā)布時(shí)間偏長(zhǎng)和線上調(diào)試?yán)щy的問(wèn)題。相比之下,YUI3的Loader下載方式則更加優(yōu)秀,其使用一種稱為Combo Handler的機(jī)制[5],它會(huì)將線上文件直接以GET的方式指定路徑,進(jìn)行動(dòng)態(tài)合并及最小化。由于受到GET的長(zhǎng)度限制,YUI Loader會(huì)根據(jù)模塊的載入順序、總數(shù)量和當(dāng)前瀏覽器的GET長(zhǎng)度限制等信息自動(dòng)將Combo Handler的請(qǐng)求分散為若干個(gè),進(jìn)行并行下載,這樣就解決了RequireJS遇到的問(wèn)題。
3 結(jié)束語(yǔ)
由此可見(jiàn),依賴當(dāng)前出現(xiàn)的多種框架及工具,并加以適當(dāng)修改就可以很好地實(shí)現(xiàn)模塊級(jí)模塊化開(kāi)發(fā)策略,從而有效地解決了前端模塊化開(kāi)發(fā)中的諸多問(wèn)題,既便 于團(tuán)隊(duì)開(kāi)發(fā),又具有發(fā)布快、易于線上調(diào)試及維護(hù)、提高性能等優(yōu)點(diǎn)。但與此同時(shí),新問(wèn)題也在不斷涌現(xiàn),例如頁(yè)面模塊的劃分、模塊的粒度和模塊的繼承等都還存 在很多問(wèn)題,這些都需要前端開(kāi)發(fā)人員繼續(xù)努力去解決,進(jìn)而完善模塊化開(kāi)發(fā)策略。