之前的專案一直採用grunt來構建,然後用requirejs做模組化,requirejs官方有提供grunt的插件來做壓縮合併。現在的專案切到了gulp,模組化用起了seajs,自然而然地也想到了模組合併壓縮的問題。
然後一開始在解決這個問題的時候,並不是很順利,在npm上並沒有那種特別流行的專門用來做seajs合併壓縮的gulp插件,雖然在seajs的github上也看了不少的issue,但是大多數都是只能將所有的模組文件合併成一個總的文件,這對於單頁面的應用來說肯定沒有問題,但是對於多頁面的應用而言,顯然就違背了模組化思想中按需載入的核心,所以我想要的是一個能夠根據我每個頁面各自所依賴的模組來按需合併的方法。
這個按需合併的意思,一方面是只合併一個頁面所依賴的那些模組,另一方面是,還能過濾掉某些模組不參與合併,考慮這個的原因在於有些模組,比如jquery等,都屬於第三方依賴的函式庫,可能檔案比較大,最重要的是你幾乎不會去改動它的程式碼,所以這些模組不會合併到頁面的js中,會有助於更好地利用瀏覽器快取。本文介紹一個簡單可行的方法,來做基於gulp建構的中小型專案中的seajs合併壓縮。
以login.html為例,查看這個頁面的來源檔案中,會看到它除了引用seajs以及相關的設定檔common.js外,只引用了app/login作為頁面的main js,這個app/login模組其實對應的就是js/app/login.js:
但實際上,這個login.js依賴了更多的模組js,你可以透過chrome的soures來查看該頁面載入的詳細js資源:
在login.js合併之前,它的程式碼是這樣的:
但是在前2個截圖中,我們並沒有看到mod/mod1.modjs, /
但是在前2個截圖中,我們並沒有看到mod/mod1. js , deps/fastclick.js這三個文件,我們除了看到login.js,還看到了lib/bootstrap.js , lib/jquery.js , lib/jquery.validate.js。這就是合併的效果。一方面保持了js/lib資料夾下的模組都不會參與合併,另一方面保證了頁面的main js所依賴的其它模組,都合併到頁面的main js檔案中來。 1. 合併思路其實方法還算比較簡單,我最後再介紹。 1)我先說下自己對seajs的模組進行組織的一種資料夾結構,它是這樣的: 這個結構藉鑑於requirejs,盡量讓文件組織扁平化,對於中小型前端項目來說,應該不會太麻煩。其中各個資料夾的功能是:
1)js/app 存放各頁面的main js,基本上就是一個頁面一個js的邏輯
2)js/deps 存放哪些需要合併到main js的第三方模組
3)js/lib 存放哪些不需要參與合併的第三方模組
4)js/mod 存放各個專案中自己寫的一些js模組
3)合併的想法:主要是利用gulp-seajs-transport和gulp-seajs-concat這兩個gulp插件。雖然它們在github上不是很熱門,但是已經很好地解決我的問題了,使用起來也非常簡單:
(更多內容需要查看本文開始處提供的源碼鏈接,找到相關的gulpfile. js檔)
gulp-seajs-transport可以幫助你把seajs的模組檔從匿名模組,變成具名模組。例如js/mod/mod1.js在建置前是這樣的:
但是經過transport處理後就會變成:
這個是seajs合併工作中比較關鍵的一點,它不像requirejs ,直接做concat即可;它必須先經過一個transport的任務處理,將匿名模組變成具名模組,同時用define的第二個參數來描述這個模組的所有依賴,就像requirejs那樣。做完了transport,才能利用gulp-seajs-concat做合併。
gulp-seajs-concat做合併的時候,就很簡單了,只要告訴它一個base選項即可,這個base選項跟js/common.js中base選項保持一致。因為gulp-seajs-concat根據base和transport之後的模組,就能找到它所依賴的其它模組檔。
4)頁面中使用main js時要採用這種方式:
use的參數名稱,必須跟合併之後的main js的主模組ID保持一致。例如js/app/login.js合併之後是這個樣子:
第一個define對應的模組就是合併後文件內的主模組,紅框的內容就是該主模組的id,seajs use這個模組的時候,參數名稱必須跟這個id一致。否則seajs即使成功的載入到了這個文件,也不會執行任何模組內的程式碼。因為seajs有一個規則:ID 和路徑匹配原則,其中有點跟這個相關,就是:當seajs use到一個文件內包含多個模組時,會根據use的參數名稱來尋找這個文件內的主模組,只有它們完全匹配,才能找到。
5)壓縮混淆:使用gulp-uglify:
但是要注意那個mangle,必須把require exports module排除掉,否則會引發一些意外的問題。
2. 本文小結
本文內容雖然很簡單,但是在剛切到gulp和seajs的時候,還是費了不少時間才把本文的問題解決,雖然在準備demo的時候進展地比我當時的情況要順利的多…不管怎麼樣,希望本文的內容多多少少能幫助一些朋友。
更多基於gulp合併壓縮Seajs模組的方式說明相關文章請關注PHP中文網!