Angular 4 folders-by-feature structure practice

Angular 4 切版實戰 part 1: 新手上路甘苦談

註:未來 AngularJS (1.x) 後的版本統稱 Angular,不過為了方便理解暫且稱為 Angular 4,而且現在 Google "Angular" 的資訊也大多還是在講 AngualrJS

雖然字面上是甘苦談,但就是苦談的意思。之後可能會變成系列文,當作開發過程中的心得整理。

寫 AngularJS (以下簡稱 A1) 習慣之後,現在寫 Angular 4 (以下簡稱 A4) 有種打掉重練的感覺。尤其看著寫過 VueJS 的夥伴 Eric Yip 迅速寫完一堆 A4 的 component 和 service ,更加充滿徬徨。

寫過 Angular 1 的朋友們,一定懂 A1 directive 和 A4 Component 之間的大鴻溝,一開始只能稍微抓到 Component 可實現降低相依性、內部可獨立運作不影響外界邏輯。但真的實作起來,碰到了第一個難題:資料夾怎麼分?

文件告訴我們用 feature 來分。

feature 是甚麼……
shared 資料夾 ??? (腦中只有新垣結衣在吶喊シェア的畫面)

明明當前端工程師兩年,此刻的我感到自己是如此的新鮮:D

於是大腦自行產生了 一切都是幻覺嚇不了我的 精神勝利法,第一版我們參考 AngularClass/angular-starter 切出來長這樣:

註:由於是開發 CRM 系統,customer-list 代表顯示 user 的客戶列表。另外只列出少部分的資料夾當範例解說。

app 
--view
----home // home page
----customer-list // customer list page
----no-content // 404 not found page
--component // all the contents in page
----customer-profile // single customer component
----header
----nav

哇 component 和 view 平行了喔好棒棒~~~?


前輩:feature 完全沒分出來啊 = = 要用服務本身的特性來區隔,一個 feature 底下可以有很多 component 和 service,他們一起完成某樣同質性的任務

我:可是假設現在有三個 feature,
1. profile feature: 專門產生個人資料頁面
2. business-card feature: 專門產生個人名片頁面
3. user feature: 專門處理個人資料相關的服務
而 1,2 的 feature 都要用到 3 提供的資料才能完成任務。這樣感覺 3 的地位和 1,2 不一樣,不該視為平行的 feature 阿?

前輩:那 user feature 就放到 shared 裡面阿!

我:!!!(⊙o⊙)

前輩:然後 feature 底下也可以有自己的 shared 資料夾,給 sub feature 使用,所有的 feature 都要盡可能平行,減少相依性 (減少 parent-child 的關係)。

我:!!!(⊙o⊙)


前輩一點醒,頓時如醍醐灌頂。原來 shared 的意思是,同樣層級的 feature 共享的內容!第二版打版成果:

app
--core // for one-time loading components/services
----header
----nav
--home
--customer
----customer-list // customer list
----customer-profile // single customer profile
----shared // share with all thing under customer feature
--shared
----no-content

使用 feature 所切出來的版,可以整理為幾項重點:

  1. 使用 feature 來管理權限作用的區域:一般預設 feature 要盡可能平行,當某 feature 底下需細分管理,則代表限制了它的作用不會影響到父層。
    譬如 customer-list 不可 import home component,但 home可以 import customer-list。
  2. app/customer/shared 裡面的內容只能在 customer 底下被使用,若在未來 home 也需要用到某支 app/customer/shared 的內容,則他應該要搬家搬到 更上層的 app/shared 裡面。
  3. 目前這一點還未實作,不過我推測未來若 customer-list 畫面需要和 customer-profile 同步,customer-list 不可直接 ngRepeat customer-profile.component,而是要在 app/customer/shared 裡面添增一筆單筆客戶資料的 component,由 customer-listcustomer-profile 各自去 import 來用。因為萬一哪天customer-profile 頁面改了,才不會影響到 customer-list 顯示的結果。

雖然才剛開始寫 component,有點懵懂抽象的概念,但實作成功就可以免除了每次維護都要尋找哪些元件有相依性、改一個元件結果頁面都要一起修正的地獄。現在新生之犢不畏虎,希望在 Angular 的世界可以殺出一條血路!