1. 程式人生 > >快速web開發中的前後端框架選型最佳實踐

快速web開發中的前後端框架選型最佳實踐

這個最佳實踐是我目前人在做的一個站點,主要功能:

oauth登入

釋出文章(我稱為"片段"),片段可以自定義一些和內容有關的指標,如“文中人物:12”。支援自定義排版、插圖、建立相簿。

多個片段可以組織在一起,形成"事件"。

任意事件、片段都可以互相標記因果關係。

可以follow事件或者他人。

事件和片段模糊搜尋。

我對目前前端框架的觀點已在另一篇文章中講過,這裡只介紹一下目前實踐的情況。

使用requirejs做模組化,上線時用r.js打包。

使用avalon做資料與檢視渲染框架。

用page.js來管理路由。

用harp來做靜態資源伺服器。harp支援less、coffeescript等自動編譯,當前端有css或js請求而相應的檔案不存在時,它就會自動查詢同名的less或coffeescript等檔案並編譯輸出。

後端選型經歷了兩週左右,目標無非兩個:開發便捷,適用於生產環境。

我對開發便捷的要求是。

可簡可繁的路由配置,且非常容易生成REST介面。可棄用框架自帶的檢視層。

框架有一個良好的資料庫層,可以是ORM也可以是AR。這個資料庫層同時要支援開發者手動優化查詢。

框架依賴少,容易安裝和部署,社群支援強大。

對適用於生產環境的要求是:

框架本身輕巧,速度快。

支援大併發,有成熟叢集部署方案。

能切換各種型別的資料庫,有memcached等快取中介軟體的介面。

在這期間,我試用了Django、drupal、discuz、codeigniter、expressjs、sails,以下記錄選擇過程中對前後端的考慮,希望對有類似需求的朋友有幫助。我的定論留在文章最後。

Django

比較慚愧,出於個人對python不如php和nodejs熟,放棄了Django。Django自帶功能非常強大的ORM,有REST中介軟體。也有成熟的部署方案。並且有非常好的學習指南(搜"Django book"),推薦各位一定要自己用用。

drupal

要完整地描述和概括drupal有一點難。它既不是某一種具體業務邏輯的框架(把它說成CMS太狹隘),也不是純粹的只有功能層面(如ORM、檢視渲染)的框架。只能這樣說:

首先,它包含了強大的功能層,如資料庫層、檢視層。其次,它通過“hook”機制以及一整套完善的附屬功能,讓開發者能非常自由地打造自己的業務邏輯。或者說使得它可以幾乎可以包容任何業務邏輯。類似於AOP,類似於裝飾類。

這裡為不懂的讀者再介紹一下它的核心“hook”。實現一個hook有兩步:一、在業務流程中的某些點宣告可以被hook。二、宣告一個操作,和它要hook到哪個流程中的點。比如:一個使用者註冊模組宣告,在獲取使用者的註冊資料後,寫到資料庫之前,這一點可以被hook。一個加密模組宣告,要對註冊資料中的密碼進行加密,並宣告這個操作hook到剛才提到的使用者模組宣告的點上。這樣在寫到資料庫前,密碼就被加密了。

hook機制早已有之,drupal的精髓在於將其發展並運用到幫助開發者實現業務邏輯上。因為幾乎任何人類的業務邏輯都是流程化的,並且很可能變化。hook滿足了在不直接改變原有邏輯的情況下進行擴充套件和修改的需求。也是這種機制激活了drupal的開發社群,讓它的每一個模組都能很好地與其他模組協作。

一開始我其實是選用了drupal做後端的。第一,它的後端功能十分完善,從使用者註冊到內容管理應有盡有。實在沒有還可以去它強大的社群找支援。第二,drupal在部署、效能優化方面已經非常成熟。但最後仍然棄用了,這裡先說說用的過程。

首先裝上Service模組自動實現drupal的REST api,這時候節點、使用者什麼的增刪改查介面就已經都有了,只需要按照Services的說明去開啟這些介面就行。如果需要跨域呼叫,還要裝上CORS模組來允許跨域請求,相關知識請自行google CORS。如果定製更多的查詢介面,可以裝上Services Views模組,它能直接將views生成的列表變成資料輸出,不過這個模組和views本身一樣有個讓人很不爽的點:對於多值的欄位,不能按陣列輸出,只能輸出成一行字串,以",“或者其他指定符號分割。

至此,後端已基本可用。然而隨著繼續開發,有了更多的需求,比如說投票。drupal有很多投票模組,但幾乎都是直接嵌入到頁面中的,對api支援不好。於是想自己寫一個。這樣的功能多了以後發現,去找有沒有類似模組,並調研是否符合我需求和踩坑的時間都已經超過了自己開發的時間。如此一來都已經脫離我”快速開發“的本意了。況且如果都要自己寫,為什麼不選個輕量級的框架呢?比如codeigniter。於是開始便繼續寫,邊尋覓其他框架。drupal整體而言其實應該是非常適合團隊開發的,因為它迫使大家都遵循同樣的機制,這樣就解決了團隊開發容易質量不可控這樣一個最大的風險。對個人開發者來說,總是先搭個架子,或者先看看別人的架子是怎麼搭的,再開始寫程式碼,實在有點累。

discuz

看完drupal再看discuz、phpwind什麼的,完全不能接受,架構太亂,控制器、模型、檢視耦合嚴重。沒有對REST api好的支援。略過。

codeigniter

codeigniter確實是非常輕,一個自動對映到控制器的路由系統,一個以AR方式實現的資料庫層,一個可用可棄的檢視層。就這麼簡單。codeigniter同樣也有良好的社群支援,然而更重要的是,正是因為它非常簡單,讓它可以幾乎無痛的與任何第三方類庫整合。不過自己的業務邏輯,就得一點一點自己搭建了。如果是這樣的話,那還是用nodejs的框架更好。

expressjs

expressjs是我所知的目前最成熟的nodejs框架了(如有其它更好的,只能說我孤陋寡聞了)。選nodejs框架最大優點:第一,沒有切換語言程式設計的痛苦。第二,nodejs在處理併發、大規模部署都已經有成功經驗。第三,能夠良好地支援各種資料庫。如果不是發現了sails的話,我應該就選expressjs了。

sails

對我個人來說,對小框架其實是有戒心的。特別是對於要上線的程式,萬一碰到問題問作者,作者撒手不管,也沒有大規模部署的例子等等情況,上線後可能就會面臨推倒重來的結局。所以不能只看開發體驗,框架的出身也是很重要的。首先值得說明的是,sails是基於expressjs的。 稍微讓人放心了點。其次,sails雖然自稱實時框架,強調自己對於web socket的封裝。但我目前只需要用到它的ORM和自動生成REST api。畢竟這兩個基礎的東西看看原始碼是可以自己掌握的。下面來介紹以下實踐過程:

首先是路由系統。分為兩個部分,一個是sails對每一個model自動生成的REST api。sails支援標準的REST請求,同時也能讓開發者通過配置檔案將介面修改為常用的REST變種介面。另一部分是使用者自己定義的介面,和codeigniter一樣,sails也是自動將介面對映到相應controller的方法上,非常簡單。它同時還提供了稱之為polices的機制來保護介面,即在呼叫指定介面之前先用定義好的police檢測一遍,不通過則直接拒絕請求。這樣能讓controller更專注於具體業務邏輯。

然後講講資料層。sails的資料庫介面卡非常多,幾乎所有的主流的資料庫都能支援。它也是通過寫配置檔案,來實現對欄位的定義。一個叫做'Event'的模型例子:

module.exports = {

  attributes: {

        uid: {

            type : 'string',

            defaultsTo : ''

        },

        title: {

            type:'string',

            required : true,

        },

        content : 'string',

        vote : {

            type : 'integer',

            defaultsTo : 0

        }

    },

    afterCreate:function( event,next ){

        Heat.create({

            entity_id : event.id,

            type : 'event'

        }).done(function(){

            next()

        })

    }

};

在這段程式碼裡可以看出,sails的定義實現了主流資料庫中對欄位的檢測、設定預設值等功能。值得一提的是例子最後的'afterCreate'函式,這是sails提供的類似於drupal hook的東西,它自己稱為"生命週期回撥"。它可以讓開發者在模型的增刪改查前後自動執行相應的管理操作。在我們的例子裡就是在一條屬於Event模型的記錄建立之後,再建立一條相關的Heat模型的資料。

要注意的是sails ORM中是沒有自動支援模型建的關聯的。以我個人的觀點來說,正好也不需要,因為模型間的關聯常常是造成資料庫查詢負載的罪魁禍首,我常常通過儲存冗餘資料等方法來儘量減少關聯查詢。所以不支援模型關聯,正好讓我每一個需要關聯的地方都手寫,保障效能。

資料庫我用了mongodb,我的需求裡面有些非結構化的資料可以無需任何轉換地存到資料庫了。sails同時還支援對不同的model使用不同的資料庫,這樣未來要對資料庫調優的話空間就很大了。

最後看看下對CORS的支援,直接在整站的配置檔案中開啟crsf選項即可。對於跨站請求,先請求crsf token,之後的請求帶上這個頭就可以跨站了。

結論自然是選擇了sails。目前sails整體專案官方維護得非常積極,功能完備。實在有問題了看看原始碼也能夠明白。相對於我的需求來說已經非常好了。

最後整體總結一下:

1.整個開發中前後端完全分離。後端只提供資料介面,並且支援跨域請求,也便於之後進行其他端的開發。

2.前端用avalon、requirejs、page.js三件套開發體驗非常好。用harp來支援less和coffeescript等,自動編譯,無需任何中間操作。

3.後端用sails來處理業務邏輯和提供REST api。各種功能齊全,開發順暢。

文中內容若有偏頗,望不吝賜教。預祝螢幕前的你新年快樂。