angularJs項目實戰!01:模塊劃分和目錄組織

近日來我有幸主導了一個典型的web app開發。該項目從產品層次來講是個典型的CRUD應用,故而我絕不猶豫地採用了grunt + boilerplate + angularjs + bootstrap + D3 + requirejs 的架構來實現它。angularjs早在去年6月份我就有所接觸,將它應用在實驗室項目的個別頁面中,11月份在新浪的時候也將其推薦給了所在雲事業部項目組。項目組老大程輝等人都是頗有技術敏感性的人,大膽地採納了個人建議,將之應用於本來使用dojo開發的項目前端模塊上。然而,因爲前端模塊很大,而且已經用dojo開發了很長時間了,故而angularjs一開始也是應用在一些頁面和子模塊上,至我離開新浪以前還完成所有的重構。雖然以後我也作過一些angularjs的插件之類的事,但終究沒有用angularjs完整地搞一個大型項目的經驗。故而此次實驗室交予我一整個項目,且無論所得利益幾何,對於一個對前端有愛的人而言,這是一次從頭開始完整地進行angularjs項目實戰的機會,我怎麼可能放過。期間種種我都想用博客記錄下來,以備後用。javascript

開發大型javascript應用和作幾個demo頁面玩一玩最大的區別在於,要對一開始的文件組織和模塊劃分要有更清晰的認識。這項工做前期花了我較多的時間去處理。故而第一篇文章就寫模塊劃分和目錄組織,這方面本人經驗很少,不足之處敬請指出。css

 

項目需求和資源評估

沒有什麼模塊劃分是必須的和通用的,模塊劃分都是在對項目需求、手頭資源(員工資源、時間資源和物質資源)有充分的評估,同時參考大量範型的基礎上做出決定。因此先大體介紹一下我接手的項目需求。這是一個典型的B/S架構的呈報系統軟件。要求有用戶-服務檯-辦事人員-系統管理員四級的角色架構,針對不一樣的角色,顯示不一樣界面,每種界面內含子頁面大約20個不等,子頁面互相有重複。需求要求系統有足夠的穩定性,通常的併發性。前端要求有設計感,足夠美觀,快速響應,對一些特定統計內容有相應的可視化呈現。不需支持IE6。項目成型後,做爲軟件安裝部署,二次開發可能性較小。人力資源方面,加上我幹活的有三個,其中前端熟練工一個(俺),有必定開發經驗的一個,編寫代碼通常可視化程序操做優良踏實肯幹的一個。時間資源大約3人*60個工做日。html

根據項目需求可知,項目從用戶角色可劃分爲四個大模塊:用戶、服務檯、辦事人員、系統管理員。大部分頁面邏輯較爲單一,易於劃分。對於重複子頁面可另創建通用模塊。考慮到人力方面,2/3是非熟練工,美工設計人員基本沒有(原本我是,可是如今的工做量不容許我作這個了),工程量大時間緊,故而要求將設計的工做量降到最低。使用的技術和模塊劃分要儘可能易上手,減小重複勞動,提升併發效率。因爲前端人員較多,後臺較爲簡單,故而總體架構上,後臺只須提供REST風格的API,將工做重心前移,前臺負責主要邏輯模塊的實現。前端

 

前端初始架構設計

在確認了需求和資源評估以後,本人接下來的工做是在github上遍覽使用了angularjs的各類項目,以及google相關文檔。其中github上的幾個project給我了我較大啓發,它們分別是:html5

根據這些參考內容,我設計了初始的技術路線,如圖所示:java

web_front_end_before

簡要說明一下:node

web server使用的是node.js。同時配以自動化工具grunt作一些端到端測試、代碼壓縮和合並之類的工做。jquery

framwork固然用的是angularjs作MVVM框架。同時用了一些UI小插件,如angular-ui-bootstrap, angular-ui和我本身寫的表格插件angrid(https://github.com/zhangdiwaa/anGrid)。由於表格插件對於本項目來講比較重要,這裏採用本身寫的表格插件主要是爲了便於定製(想當年爲了定製dojo的表格插件改得要吐)。在模塊劃分上,一開始是模仿angular-seed的方式,就用一個myApp做爲程序入口點,direcvtives、filters、service做爲文件夾,存放對應的js文件。git

基礎的工具集採用jquery以及bootstrap。bootstrap這個東西的好處就在於能夠快速地讓不懂設計的人也能快速開發出能看的界面,搞定不挑剔的用戶足夠了。況且國內還有不少軟件系統的界面遠不如bootstrap好看。這裏bootstrap咱們沒有使用其開發包而是直接使用它的工程包,而且摒棄了less。這樣作由於考慮到需求咱們並不須要對bootstrap作多少定製化處理。直接使用原始設計,將樣式設計的工做量降到最低。less這個東西,只在須要很是頻繁變動樣式設計的時候方顯本事,其餘時候還不如直接用CSS。angularjs

其餘工具集主要是前端數據可視化工具包D3,D3的強大無需說明。另外把boilerplate單獨說一下是由於這東西我確實很喜歡,它是製做符合html5+CSS3規範的網頁程序的快捷方式

 

初始架構設計的問題1:angularjs沒有諸如AMD或者CMD的機制。

當我企圖以現有方案繼續的時候,發如今從myApp劃分子模塊開始就進行不下去了。問題以下:angularjs沒有諸如AMD或者CMD的機制。從myApp開始,myApp全部的依賴都必須先行加載。雖然angularjs可使用路由按需加載模板,可是控制器卻要先行加載(以下面的代碼所示)。

個人項目裏有可分4個角色模塊(用戶、服務檯、辦事人員、系統管理員),對於一個入口點壓力已經很大了,每一個模塊還有20多個頁面,難道全部的控制器、以來模塊都要所有加載嗎?這顯然不科學。必須按需加載。

因而我在網上搜了半天,首先找到的方法以下:

這個辦法至關於使用angularjs內置的ajax方法,延遲加載了js文件。然而此法並很差用。在每一個控制函數後面都寫個延遲加載屬性方法顯得很笨,固然,你能夠把它寫到prototype去或者改angularjs源碼,但那樣作頗有多是給另外兩個非熟練開發人員埋地雷。總之延遲加載controller問題多多,尤爲是在顯示的時候,具體你試試就知道了。

因而我想到了require.js這個AMD工具。之因此用require.js而不是國產的seajs並不是我歧視國產(事實上我上一個項目就用的是seajs),而是由於require.js文檔豐富,在github上有不少例程,適合教其餘兩個開發人員使用。除此之外require.js的AMD模式跟dojo的AMD按需加載方式一模一樣,所以使用過dojo開發的我對require.js更有好感。因而我最終仍是使用了require.js作AMD方式的按需加載。

更進一步地,github上還有人基於RequireJS寫了在angular路由時動態加載templete,controller,和directives的插件。在模塊較少較清晰的狀況下,這樣已經夠用了。 https://github.com/matys84pl/angularjs-requirejs-lazy-controllers

 

初始架構設計的問題2:咱們的程序真的只須要一個app作入口點嗎?

在angularjs的教程中,老是使用一個入口模塊(一般是叫myApp)來組織整個程序。不管是angular-seed,phonecat這樣的示例程序仍是像NJBlog這樣的比較大的應用都是一個入口點。可是,咱們的項目跟這些都不一樣,是一個比他們都大的多、複雜的多的項目。因爲本項目中的角色之間功能是嚴格分離的,因此產生了四大角色模塊用戶、服務檯、辦事人員、系統管理員,它們之間是不會串門的。因此這4個模塊徹底能夠用4個app作入口點來組織程序。最後再加上一個登錄模塊,作斷定和跳轉便可。使用requirejs最怕的問題就是依賴關係太多從而產生混亂,而這樣劃分5個入口的方式決定了每一個app的依賴都不是太多,整個程序的功能邏輯一目瞭然。

雖然事實上,採用一個入口點,而後經過內部機制判斷,從而在各個模塊之間跳轉也是可行的,可是那樣程序複雜度就要高的多,還要給另外兩個搭檔解釋都要解釋半天,因此仍是算了吧。

 

初始架構設計的問題3:按模塊組織文件

一開始的時候,個人文件目錄徹底是照書抄書仿照angular-seed進行組織的。考慮到文件較多較複雜,因而就設置了幾個direcvtives、filters、service做爲文件夾,存放對應的js文件。因而文件目錄看起來就像下面這個樣子:

  • controllers/
    • LoginController.js
    • RegistrationController.js
    • ProductDetailController.js
    • SearchResultsController.js
  • directives.js
  • filters.js
  • models/
    • CartModel.js
    • ProductModel.js
    • SearchResultsModel.js
    • UserModel.js
  • services/
    • CartService.js
    • UserService.js
    • ProductService.js

可是這樣真的好用嗎?

看起來文件排列的是很整齊,可是叫個人搭檔來看,他依然不清楚這些對象的依賴關係。尤爲當要重用某些模塊的時候,他必須從各個文件夾中搜集相關文件,並且經常會遺漏某些文件夾中的對象。

事實上,在快速開發中確實不多會在新項目中重用不少代碼(重複代碼倒有不少),但極可能須要重用登錄系統這樣的整個模塊。

因此,不如按照功能模塊去組織文件夾。最終,個人目錄是這麼排列的:

  • build/(工程目錄)
    • css/
    • img/
    • js/
      • appAdmin/  (獨立模塊,以app名字開頭,各app模塊內容近似)
        • controller/  (相關的子模板的controller.js存放在這裏)
        • directives/  (相關的directive.js存放在這裏)
        • admin_app.js  (app模型定義和路由配置文件)
        • admin_main.js  (requirejs的入口和配置文件)
        • admin_services.js  (app的相關服務配置文件)
      • appCustomer/
      • appHelpdesk/
      • appRepairer/
      • appLogin/
      • common/  (通用模塊庫)
        • angular_filter/  (一些通用的過濾器)
        • common_plugin.js  (一些非基於angular的但比較重要組件,例如console plugin)
      • utils/  (其餘組件)
    • lib/  (包含全部第三方類庫)
    • templete/  (子模板文件夾,其內容按模塊類型分類)
      • common/
      • tplAdmin/
      • tplCustomer/
      • tplHelpdesk/
      • tplRepairer/
    • 404.html
    • admin.html  (admin模塊的入口html)
    • customer.html  (customer模塊的入口html)
    • helpdesk.html  (helpdesk模塊的入口html)
    • login.html  (login模塊的入口html)
    • index.html  (程序的總入口點,用以根據配置跳轉到各個模塊入口)
    • repairer.html  (repairer模塊的入口html)
  • node_modules/  (grunt)
  • src/  (未經grunt處理的源文件)
  • test/  (端到端測試)
  • gruntfile.js  (grunt)
  • human.txt
  • package.json  (grunt)
  • README.md

顯然,這裏我將js和templete裏面的文件都按模塊劃分爲一個個子文件夾,在build的根目錄下留下了數個模塊入口點。這樣已經足夠清晰了。

還有更爲激進的作法,就是將屬於同一個模塊的templete、css、js全放在一個模塊目錄下,我上一個項目就是這麼作的。可是上一個項目未能清晰地劃分通用模塊和功能模塊,形成了必定混亂。我暫時很差比較這兩種劃分的優劣。至少以目前的劃分,已經足夠可用了。

相關文章
相關標籤/搜索