1. 程式人生 > >Angular2的模塊架構淺談

Angular2的模塊架構淺談

a

一、根模塊、子模塊與惰性加載


先說根模塊。一個ng2應用至少要有一個根模塊,包含ng2自帶的BrowserModule,並聲明為引導模塊,在應用啟動時將從此模塊展開。
隨著應用的擴大,所有的事情都在一個模塊中完成難免會變亂(某種程度上看ng1應用就是這麽做的,並且細分了控制器來拆分應用,這其實浪費了最頂層模塊的意義),所以自然而然能想到,可以將系統分為多個模塊,每個模塊都只做各自的事情而互不幹擾,所以進一步的思路就是,用來根模塊來引導程序並管理所有子模塊(通過路由定向以及為它們提供全局配置與服務實例),所有的具體業務就交給各個子模塊來完成。
然後會有一個問題,那就是既然系統已經被這麽多個子模塊瓜分了,並且這些子模塊也不可能同時全部都會被使用,也就是只有其被激活時才有用,那仍然在應用引導時從根模塊加載所有子模塊必然會導致性能的浪費以及拖慢執行速度。此時惰性加載模塊就派上用場了,將一個子模塊定義為惰性加載後,只有在通過路由激活此模塊時才會開始加載此模塊(並且ng2甚至支持異步預加載,即後臺預加載懶加載的模塊,這樣當懶加載模塊需要被加載時其實其已經加載完成了,又加快了響應速度)。


二、除了模塊之外


每個模塊都有自己的事情要做,通常包括:

  1. 引入其他模塊 這個在第三部分細說


  2. 聲明模塊包含的組件、指令與管道 所有的組件、指令或管道都必須依附於某個模塊,並只在此模塊中可用。


  3. 定義模塊提供的服務       服務也有自己所屬的模塊,但由於服務是全局單例的,所以只要在一個模塊中提供之後,全局都通用。註:若多個模塊同時提供了服務(通常發生在模塊間混亂的import時),一般情況下ng2能識別並只保留一個實例,但在惰性加載的模塊中則會發生不可預計的錯誤,所以一定要避免。


  4. 定義模塊將導出的組件、指令與管道(還可以是此模塊引入的模塊) 與(1配合使用,同樣在第三部分細說。

三、模塊的關聯


模塊之間一定要有共享或繼承資源的方式,不然的話每個子模塊都必須實現可能用到的全部功能。

比如一個消息彈窗組件,不可能每個子模塊都自己聲明一個消息組件然後使用,這樣的維護壓力很大且代碼嚴重浪費。

此時就用到了模塊的引入和導出——
模塊A可以引入另一個模塊B,然後A就可以使用B中導出的組件、管道和指令。

技術分享

當我們要使用系統指令(如ngIf、ngFor等)時,也必須引入系統模塊,有一個巧妙的辦法就是實現上圖這樣的共享模塊,在引入系統模塊並導出的同時再導出自定義的其他指令、組件或管道。然後所有引入了此共享模塊的子模塊就能使用這些系統指令和共享指令了。


有一個基礎的問題是服務需不需要導出,答案是否定的。服務不需要導出,因為服務是全局單例的,一旦被初始化,就已經全局通用了,相反如果重復的導入提供了同一服務的模塊就可能發生問題:
B提供服務B_S,A導入了B,C也導入了B。這種情況下ng2會找到兩處B_S的提供,但ng2尚能夠將其保持在一個實例B_S。但若模塊C為惰性加載的模塊,在C被創建時,其實會重新初始化一個實例B_S,從C跳轉回到A時,又會創建一個B_S,來回每次跳轉都是如此,結局就會變得混亂不堪。
對於服務更好的做法是寫一個核心模塊,專門提供全局服務,保證此模塊只會被根模塊引用一次,然後所有的子模塊就都已經可以使用這些全局服務了。

四、ng2模塊體系


最後給出一套ng2項目構建的體系,這也是總結歸納了ng2官網的推薦得出的ng2項目的模塊體系。

技術分享


總體思路就是:


> 1.根模塊負責全局的路由。


> 2.核心模塊負責全局服務,也可以定義一些只在根模塊中使用的組件等,並只能由根模塊引入一次,不再導出。


> 3.共享模塊不做服務的提供,而是定義全局共享的組件等,以及幫助子模塊導入系統模塊,讓子模塊只需要導入此共享模塊就夠了。


> 4.子模塊內部可以細分自己的子路由到具體的子組件,以及提供自己的服務等。


> 5.除了頁面入口模塊(即除了根模塊外的具體業務模塊)之外的其他子模塊均考慮寫成惰性加載的模塊,以提升頁面引導的速度減少性能浪費。


> 6.當需要一個比較通用的全局服務時,可以將其加入CoreModule,也可以再創建一個僅被根模塊引入的特性模塊。進一步的,甚至可以將此模塊發布到npm,這就需要更強的編碼能力和技術積累了。


Angular2的模塊架構淺談