如何將一個已經上線的項目前端部分平滑過渡至組件化和工程化?
應該有很多公司在起步的時候,並沒有太注重前端架構。比如簡單粗暴地使用像 PHP include() 之類的方法去提取公共部分,沒有使用模板引擎;頂多用個 Less 去 import 一些公共部分,JS 也只是各種 http://window.xxx 全局變數污染。
當項目規模越來越大、開發人員越來越多、需求越來越複雜的情況下,如何以儘可能以平滑的狀態過渡至前端組件化、工程化?我知道有像 FIS、Scrat 等這麼高大上的工具, 在一開始就使用肯定會很方便,但關鍵是如何將已有的項目改造成能使用這些工具,以達到完成組件化和工程化的目的呢?
瀉藥,如果接手到一個 全局變數滿天飛,沒什麼模塊力度,一個文件上千行,整站就幾個js文件,編寫毫無章法,模板中內嵌js變數和調用全局方法,模板數量龐大,這種情況,重構確實不好做。
遇到問題解決問題,我們把複雜的事情抽象一下。這個過渡到底要做什麼。
1,不影響線上項目運行。
2,代碼重構。3,引入自動化工具,解決複雜容易出錯,並人力吃緊的點。4,規範上線流程,前端開發流程。5,模塊化前端代碼,讓以後的開發可以像搭積木一樣。如果以上幾點算是共識,那麼一條一條解決就好了。市面上的輪子很多,但是還是要找到自己的問題,再找合適的輪子來用。
1,不影響線上項目運行。
如何做到呢?我的經驗是,不動老的代碼,在完成了新架構的設計後,先在新的模板和項目上進行操作。達到不繼續「亂」的局面。
老代碼怎麼辦?這裡要說的情況就很複雜了,比如模板中include,全局一個base.js,然後不同組件部分就是一個xxxPlugins({config:{}});這樣執行的,我覺得這種還是比較好做的。
在開始改動之前先上隔離,做好備份和回退機制(理論上應該是先上測試,但是實際情況很難)。然後讓後端配合做一個beta版或者叫隔離版,讓前端開發工程師可以在這裡做老代碼重構,一直到結束測試(如果資源不允許,可以轉換思路比如純前端自己做本地代理實現幾個重要頁面的重構),再讓後端配合修改模板。
這個地方主要還是看實際項目老代碼的複雜度,需要根據實際情況來,我曾經重構一個類似的項目使用自己開發的模塊載入器,因為項目頁面不多,也就10幾個不同類型的,手工操作基本1個工作日就完成了。當然老代碼寫的還是比較規範,這個需要看具體情況和具體代碼。
總之,我的原則就是,老的能不動不要動,如果要動一定要做好隔離,做好回退,並且改之前一定要好好review老代碼,理解一下為什麼之前這樣寫。
2,代碼重構。
分幾點吧,模塊化工具看團隊喜好或者個人喜歡不多說,首先重構的概念無論任何語言都差不多,是有可以遵循的原則的,有些代碼是不需要理解他的邏輯就可以進行重構的,詳細可以參考這本書重構 (豆瓣) 里的做法,先把老代碼拆分,我們掌握了方法,還需要藉助一些輔助工具,我推薦這個:Refactoring your JavaScript code with Grasp 國內的文章比較少,是專門對js代碼進行重構的工具,比vim的replace和多數ide的find功能和replace功能要強大,當然還需要結合sed和grep對整個站點的模板進行配合修改。(如果都是js文件還好說,grasp足夠,噁心的是方法在模板中被調用,那麼就必須也要對所有的模板有修改許可權才好)
重構的目的是讓代碼可以更好被理解和擴展,然後是組件化目的。我推薦seajs或者自己做cmd管理,至於如何老代碼的cmd包裝,推薦自己閱讀以下seajs的源碼,再寫個工具,其實很簡單,不推薦官方的做法,最適合自己的工具一定是自己磨的(我就是自己磨。。)。
重構的過程很爽的,相信我,如果資源不允許我會採取新需求來了,增加評估時間來對老代碼做改善,能為工程師爭取一些時間(新需求是在老代碼基礎上來做的這種情況)。
3,自動化。
不為了自動化而自動化,但是一定要知道人力浪費在哪。不是所有工具都適合自己,首先要學會發現問題才對嘛。。比如上線之前,為了確保團隊代碼規範,使用git commit pre或者svn commit pre的鉤子工具做檢查,這是一個很好的方法,再有比如,壓縮打包合併一類工作grunt,gulp的解決方案當然也都已經爛大街了,該用就用,我們這邊還有一些好玩的做法,比如一個新需求一個branch,打tag是個體力活,自動化之,checkout有很多依賴,我們使用grunt自動checkout相關代碼?再或者部署到測試機或者線上cdn,每次都好麻煩?也可以包裝成task,攢到一起就是你們的開發規範了。
而工具真的,不重要。看你能不能快速找到痛點了。更新測試機好麻煩?寫個shell?命令行也麻煩?做個web界面?這樣其他非前端工程師也能方便部署最新代碼了。
以上這些我都做過,在我眼裡都算是自動化了。
4,上線不要過度自動,有時候該人工還是要人工,比如diff每次上線前的改變,確認按鈕,一定要人工。。
規範問題,我的建議,代碼上採取填空式的規範制度。什麼叫填空式?
解一道題,我們都是有步驟了,寫一段代碼也是應該有步驟的,初始化一個構造器對參數做規範,我們應該怎麼寫?對外的api,必須有哪些方法?我們也是可以提前設計的。我是相信開發的模式化對新人工程師是最大的規範幫助,那些什麼tab需要幾個,注釋應該用什麼格式,在我看來沒那麼重要,我是相信代碼是可以說話的,只要你的代碼開發起來有強制的模式之後,這些東西都是快速集合在代碼里的。
注釋怎麼辦?老代碼一個一個去改好,加註釋好麻煩咯。我們能不能開發個讀js文件,左右分屏,實時增加註釋工具呢?就像diff模式那種,肯定是可以的,我覺得也不麻煩,以後code review還能用的上。
其他的用commit pre就足夠了。
5,在內部分享過幾次前端模塊化的基礎知識,優缺點都有,未來的趨勢我們不好說,目前來看還是比較完善的一種解決方案了。足夠簡單的api,足夠靈活的構建方法,簡單的api,簡單的規範,我推薦我寫的這個工具 litheModule/lithe · GitHub 有node的api有前端的api,我們這邊用了很久,和seajs差不多。有使用問題可以私信和我交流。這裡上傳一個我之前培訓用到的ppt吧。http://www.slideshare.net/xiaojueqq12345/ss-49156712 內容不多,大部分都是我口述,也可以私信和我溝通。
-----------------------------
如果真的重構不來,沒有資源,無法把老代碼改善的很好。
那麼我們至少 可以 新代碼 不再寫的那麼屎。加油。這個 好像跟我們現在面臨的問題一樣!
由於歷史原因,項目基本無架構,開發都是在堆業務代碼,尤其是作為前後端都需要關注的smarty模板,到了目前模板數量已經達到實際頁面數的近十倍之多,而又沒人能夠百分百確定某一個模板是否完全沒用到,所以代碼都是只增不減,代碼的冗餘已經嚴重影響開發效率甚至性能。
就像樓上有同學說的,這個時候,重構似乎已經是必然,不過平滑還是能做到的,另起項目,在接入層分流,然後逐漸遷移。
對於一個php站點的重構改造,我想了下,大概有兩種思路:
第一種,百度fis-plus(fis-plus:史上最強大的前端工程化方案),是基於smarty模板的一種解決方案。
第二種,就是前後端分離。對於本身就是smarty的項目,我想引入fis-plus應該成本不算大,後端MC層可以不動(或者復用),只改view層,工作量稍小。
但是缺點很明顯,首先畢竟後端渲染還是PHP,渲染的性能依賴smarty的性能。其次是開發環境的耦合,前端的同學在開發時必須搭建PHP環境、發布也是無法做到前後端分開發布,這會影響版本的迭代速度。另外,如果FE同學不熟悉smarty的話,肯定又會導致上面說的模板冗餘的問題,一年半載之後又回到原點。
前後端分離是一個很大的話題,這裡我不展開了。但歸納下無外乎純靜態頁面+ajax方案,以及引入Node.js作為渲染層的方案。這種方案,對於架構改造非常之大,相當於把接入層、VC層都交給了FE,要綜合考慮人力、運維成本等因素。
但好處也很明顯,前後端完全分開,模板渲染可以很靈活,比如Node首屏直出+ajax次屏渲染,甚至嘗試使用現在很火的React作為渲染層等。至於工程化、模塊化,一旦前後端分離之後,題主所說的FIS、Scrat等大可放心去嘗試了。
對於我們,前端人力已經達到一定規模並且不斷有新人加入,綜合各方面的因素,我們最終選擇採用前後端徹底分離(引入Node.js)的方案。
將 新寫的部分進行 組件化 將新寫的部分需要用到的好用的共用組件 載入進公共包。自己使用一些自動化的方案。並開始慢慢佈道一些方案。開始在項目過程中慢慢將原來的代碼重構。(前提是不影響上線規劃和 盡量不影響其它同事的工作)慢慢影響大家做一些組件化,自動化的工作,影響其他人的代碼風格。告訴他們為啥這樣寫更好用(當然一般都會嘗到甜頭覺得好用了)。 這個是我正在做的。
小步重構,進一步有一步的歡喜
「架構師」就是在此時賣到這樣的公司的。參見文章之一:工程師之間能力的差異
以我的經驗,平滑已經不可能,重構是唯一出路。重構的過程中,還要不斷地重構。
ZHAN
目前也是準備隔離重構
收藏
隔離重構才是王道
推薦閱讀: