基于gulp合并壓縮Seajs模塊的方式說明
之前的項目一直采用grunt來構(gòu)建,然后用requirejs做模塊化,requirejs官方有提供grunt的插件來做壓縮合并?,F(xiàn)在的項目切到了gulp,模塊化用起了seajs,自然而然地也想到了模塊合并壓縮的問題。
然后一開始在解決這個問題的時候,并不是很順利,在npm上并沒有那種特別流行的專門用來做seajs合并壓縮的gulp插件,雖然在seajs的github上也看了不少的issue,但是大多數(shù)都是只能將所有的模塊文件合并成一個總的文件,這對于單頁面的應(yīng)用來說肯定沒有問題,但是對于多頁面的應(yīng)用而言,顯然就違背了模塊化思想中按需加載的核心,所以我想要的是一個能夠根據(jù)我每個頁面各自所依賴的模塊來按需合并的方法。
這個按需合并的意思,一方面是只合并一個頁面所依賴的那些模塊,另一方面是,還能過濾掉某些模塊不參與合并,考慮這個的原因在于有些模塊,比如jquery等,都屬于第三方依賴的庫,可能文件比較大,最重要的是你幾乎不會去改動它的代碼,所以這些模塊不合并到頁面的js中,會有助于更好地利用瀏覽器緩存。本文介紹一個簡單可行的辦法,來做基于gulp構(gòu)建的中小型項目中的seajs合并壓縮。
注:為了說明,seajs合并后的效果,本文提供了一個演示demo,它有兩個頁面:login.html和regist.html,分別用來模擬多頁應(yīng)用中的兩個獨立的文件,可通過以下鏈接來查看:
http://liuyunzhuge.github.io/blog/seajs/dist/html/login.html
http://liuyunzhuge.github.io/blog/seajs/dist/html/regist.html
以login.html為例,查看這個頁面的源文件中,會看到它除了引用seajs以及相關(guān)的配置文件common.js外,只引用了app/login作為頁面的main js,這個app/login模塊其實對應(yīng)的就是js/app/login.js:
但實際上,這個login.js依賴了更多的模塊js,你可以通過chrome的soures來查看該頁面加載的詳細js資源:
在login.js合并之前,它的代碼是這樣的:
但是在前2個截圖中,我們并沒有看到mod/mod1.js , mod/mod2.js , deps/fastclick.js這三個文件,我們除了看到login.js,還看到了lib/bootstrap.js , lib/jquery.js , lib/jquery.validate.js。這就是合并的效果。一方面保持了js/lib文件夾下的模塊都不會參與合并,另一方面保證了頁面的main js所依賴的其它模塊,都合并到頁面的main js文件中來。
該demo相關(guān)的代碼可通過以下鏈接進行查看:
https://github.com/liuyunzhuge/blog/tree/master/seajs
1. 合并思路
其實方法還算比較簡單,我最后再介紹。
1)我先說下自己對seajs的模塊進行組織的一種文件夾結(jié)構(gòu),它是這樣的:
這個結(jié)構(gòu)借鑒于requirejs,盡量讓文件組織扁平化,對于中小型前端項目來說,應(yīng)該不會太麻煩。其中各個文件夾的作用是:
1)js/app 存放各個頁面的main js,基本上是一個頁面一個js的邏輯
2)js/deps 存放哪些需要被合并到main js的第三方模塊
3)js/lib 存放哪些不需要參與合并的第三方模塊
4)js/mod 存放各個項目中自己寫的一些js模塊
5)common.js 是seajs的配置文件。
2)在common.js中把js/lib下的模塊都配置到了alias選項里面,因為這些js都不參與合并,需要使用到瀏覽器緩存,alias可以方便我們在修改或升級了js/lib下的文件的時候,對這些文件的加載地址做一點更新:
base配置到了js文件夾。在模塊開發(fā)中,要require其他模塊時,我的習慣都是直接寫mod/mod1這樣的模塊標識,不用相對標識,即使要定義的這個模塊所依賴的模塊跟它存在于同一個文件夾中,這也是我為啥把base目錄設(shè)置到j(luò)s文件夾的原因,有點類似站點根目錄的感覺。
3)合并的思路:主要是利用gulp-seajs-transport和gulp-seajs-concat這兩個gulp插件。雖然它們在github上不是很熱門,但是已經(jīng)很好地解決我的問題了,使用起來也非常簡單:
(更多內(nèi)容需要查看本文開始處提供的源碼鏈接,找到相關(guān)的gulpfile.js文件)
gulp-seajs-transport可以幫助你把seajs的模塊文件從匿名模塊,變成具名模塊。比如js/mod/mod1.js在構(gòu)建前是這樣的:
但是經(jīng)過transport處理后就會變成:
這個是seajs合并工作中比較關(guān)鍵的一點,它不像requirejs,直接做concat即可;它必須先經(jīng)過一個transport的任務(wù)處理,將匿名模塊變成具名模塊,同時用define的第二個參數(shù)來描述這個模塊的所有依賴,就像requirejs那樣。只有做完了transport,才能利用gulp-seajs-concat做合并。原因請參考:https://github.com/seajs/seajs/issues/426。
gulp-seajs-concat做合并的時候,就很簡單了,只要告訴它一個base選項即可,這個base選項跟js/common.js中base選項保持一致。因為gulp-seajs-concat根據(jù)base和transport之后的模塊,就能找到它所依賴的其它模塊文件。
4)頁面中使用main js時要采用這種方式:
use的參數(shù)名稱,必須跟合并之后的main js的主模塊ID保持一致。比如js/app/login.js合并之后是這個樣子:
第一個define對應(yīng)的模塊就是合并后文件內(nèi)的主模塊,紅框的內(nèi)容就是該主模塊的id,seajs use這個模塊的時候,參數(shù)名稱必須和這個id一致。否則seajs即使成功的加載到了這個文件,也不會執(zhí)行任何模塊內(nèi)的代碼。因為seajs有一個規(guī)則:ID 和路徑匹配原則,其中有點跟這個相關(guān),就是:當seajs use到一個文件內(nèi)包含多個模塊時,會根據(jù)use的參數(shù)名來尋找這個文件內(nèi)的主模塊,只有它們完全匹配,才能找得到。
5)壓縮混淆:使用gulp-uglify:
但是要注意那個mangle,必須把require exports module排除掉,否則會引發(fā)一些意外的問題。
2. 本文小結(jié)
本文內(nèi)容雖然很簡單,但是在剛切到gulp和seajs的時候,還是費了不少時間才把本文的問題解決,雖然在準備demo的時候進展地比我當時的情況要順利的多…不管怎么樣,希望本文的內(nèi)容多多少少能幫助到一些朋友。
相關(guān)文章
通過修改360搶票的刷新頻率和突破8車次限制實現(xiàn)方法
這篇文章主要介紹了通過修改360搶票的刷新頻率和突破8車次限制實現(xiàn)方法的相關(guān)資料,現(xiàn)在刷票工具很多,這里就舉一例修改,增加搶票頻率及突破8車次限制,需要的朋友可以參考下2017-01-01JavaScript去除空格的三種方法(正則/傳參函數(shù)/trim)
個人認為去除空格最好的方法.采用的是正則表達式,這是最核心的原理,同時呢,還是有其他方法可以辦到的,接下來將介紹一下三種方法(trim)空格,感興趣的朋友可以了解下,或許對你有幫助呢2013-02-02TypeScript中type和interface的區(qū)別及注意事項
type的類型別用可以用戶其他的類型,比如聯(lián)合類型、元祖類型、基本類型,interface不行,下面這篇文章主要給大家介紹了關(guān)于TypeScript中type和interface的區(qū)別及注意事項的相關(guān)資料,需要的朋友可以參考下2022-10-10