一樣作前端,爲什麼差距愈來愈大?


阿里妹導讀:前端應用愈來愈複雜,技術框架不斷變化,如何成爲一位優秀的前端工程師,應對更大的挑戰?今天,阿里前端技術專家會影結合實際工做經驗,沉澱了五項重要方法,但願能對你的職業發展、團隊協做有所啓發。css

過去一年,阿里巴巴新零售事業羣支撐的數據相關業務日新月異,其中兩個核心平臺級產品代碼量急速增加,協同開發人員增長到數十人。前端

因爲歷史緣由,開發框架同時基於 React 和 Angular,考慮到產品的複雜性、人員的短缺和技術背景各異,咱們嘗試了各類方法打磨工具體系來提高開發效率,如下分享五點。java



1、基於 Redux 的狀態管理

從2013年React發佈至今已近6個年頭,前端框架逐漸造成 React/Vue/Angular 三足鼎立之勢。幾年前還在爭論單向綁定和雙向綁定孰優孰劣,如今三大框架已經不約而同選擇單向綁定,雙向綁定淪爲單純的語法糖。框架間的差別愈來愈小,加上 Ant-Design/Fusion-Design/NG-ZORRO/ElementUI 組件庫的成熟,選擇任一你熟悉的框架都能高效完成業務。webpack

那接下來核心問題是什麼?咱們認爲是狀態管理。簡單應用使用組件內 State 方便快捷,但隨着應用複雜度上升,會發現數據散落在不一樣的組件,組件通訊會變得異常複雜。咱們前後嘗試過原生 Redux、分形 Fractal 的思路、自研類 Mobx 框架、Angular Service,最終認爲 Redux 依舊是複雜應用數據流處理最佳選項之一。git

慶幸的是除了 React 社區,Vue 社區有相似的 Vuex,Angular 社區有 NgRx 也提供了幾乎一樣的能力,甚至 NgRx 還能夠無縫使用 redux-devtools 來調試狀態變化。web



不管如何優化,始終要遵循 Redux 三原則:redux



這三個問題咱們是經過自研 iron-redux 庫【1】來解決,如下是背後的思考:後端

如何組織 Action?瀏覽器

  1. action type 須要全局唯一,所以咱們給 action type 添加了 prefix,其實就是 namespace 的概念;
  2. 爲了追求體驗,請求(Fetch)場景須要處理 3 種狀態,對應 LOADING/SUCCESS/ERROR 這 3 個action,咱們經過 FetchTypes 類型來自動生成對應到 3 個 action。

如何組織 Store/Reducer?性能優化

  1. reducer 和 view 沒必要一一對應,應用中同時存在組件樹和狀態樹,按照各自須要去組織,經過 connect 來綁定狀態樹的一個或多個分支到組件樹;
  2. 經過構造一些預設數據類型來減小樣板代碼。對於 Fetch 返回的數據咱們定義了 AsyncTuple 這種類型,減小了樣板代碼;
  3. 明確的組織結構,第1層是 ROOT,第2層是各個頁面,第3層是頁面內的卡片,第4層是卡片的數據,這樣劃分最深處基本不會超過5層。

最終咱們獲得以下扁平的狀態樹。雖龐大但有序,你能夠快速而明確的訪問任何數據。


Redux 狀態樹


如何減小樣板代碼?

使用原生 Redux,一個常見的請求處理以下。很是冗餘,這是 Redux 被不少人詬病的緣由:



使用 iron-redux 後:



代碼量減小三分之二!!

主要作了這2點:

  1. 引入了預設的 AsyncTuple 類型,就是 {data: [], loading: boolean, error: boolean} 這樣的數據結構;
  2. 使用 AsyncTuple.handleAll 處理 LOADING/SUCCESS/ERROR 這 3 種 action,handleAll 的代碼很簡單,使用 if 判斷 action.type 的後綴便可,源碼【2】。

曾經 React 和 Angular 是兩個很難調和的框架,開發中浪費了咱們大量的人力。經過使用輕量級的 iron-redux,徹底遵循 Redux 核心原則下,咱們內部實現了除組件層之外幾乎全部代碼的複用。開發規範、工具庫達成一致,開發人員可以無縫切換,框架差別帶來的額外成本降到很低。

2、全面擁抱 TypeScript

TypeScript 目前可謂大紅大紫,根據 2018 stateofjs【3】,超過 50% 的使用率以及 90% 的滿意度,甚至連 Jest 也正在從 Flow 切換到 TS【4】。若是你尚未

使用,能夠考慮切換,絕對能給項目帶來很大提高。過去一年,咱們從部分使用 TS 變爲全面切換到 TS,包括咱們本身開發的工具庫等。

TS 最大的優點是它提供了強大的靜態分析能力,結合 TSLint 能對代碼作到更加嚴格的檢查約束。傳統的 EcmaScript 因爲沒有靜態類型,即便有了 ESLint 也只能作到很基本的檢查,一些 typo 問題可能線上出了 Bug 後才被發現。

下圖是一個前端應用常見的4層架構。 代碼和工具全面擁抱 TS 後,實現了從後端 API 接口到 View 組件的全鏈路靜態分析,具備了完善的代碼提示和校驗能力。


先後端協做簡圖


除了上面講的 iron-redux,咱們還引入 Pont 【5】實現前端取數,它能夠自動把後端 API 映射到前端可調用的請求方法。

Pont 實現原理:(法語:橋) 是咱們研發的前端取數層框架。對接的後端 API 使用 Java Swagger,Swagger 能提供全部 API 的元信息,包括請求和響應的類型格式。Pont 解析 API 元信息生成 TS 的取數函數,這些取數函數類型完美,並掛載到 API 模塊下。最終代碼中取數效果是這樣的:



Pont 實現的效果有:

  1. 根據方法名自動匹配 url、method,而且對應到 prams、response 類型完美,並能自動提示;
  2. 後端 API 接口變動後,前端相關聯的請求會自動報錯,不再擔憂後端悄悄改接口前端不知曉;
  3. 不再須要先後端接口約定文檔,使用代碼保證前端取數和後端接口定義徹底一致。

另外 iron-redux 能接收到 Pont 接口響應數據格式,並推導出整個 Redux 狀態樹的靜態類型定義,Store 中的數據完美的類型提示。效果以下:



最終 TS 讓代碼更加健壯,尤爲是對於大型項目,編譯經過幾乎就表明運行正常,也給重構增長了不少信心。

3、迴歸 Sass/Less

2015 年咱們就開始實踐 CSS Modules,包括後來的 styled-components 等,到 2019 年 css-in-js 方案依舊爭論不休,雖然它確實解決了一些 CSS 語言天生的問題,但同時增長了很多成本,新手不夠友好、全局樣式覆蓋成本高漲、僞類處理複雜、與AntD等組件庫結合有坑。與此同時 Sass/Less 社區也在飛速發展,尤爲是 Stylelint 【6】的成熟,能夠經過技術約束的手段來避免 CSS 的 Bad Parts。

  1. 全局污染:約定每一個樣式文件只能有一個頂級類,如 .home-page{ .top-nav {//}, .main-content{ // } }。若是有多個頂級類,可使用 Stylelint rule 檢測並給出警告。
  2. 依賴管理不完全。藉助 webpack 的 css-loader,已夠用。
  3. JS 和 CSS 變量共享。關於 JS 和 Sass/Less 變量共享,咱們摸索出了本身的解法:



在 scss 文件中,能夠直接引用變量:



4、開發工具覆蓋全鏈路

2019 年,你幾乎不可能再開發出 React/Angular/Vue 級別的框架,也不必再造 Ant-Design/Fusion-Design/Ng-Zorro 這樣的輪子。難道就沒有機會了嗎?

固然有,結合你自身的產品開發流程,依舊有不少機會。下面是常規項目的開發流程圖,任何一個環節只要深挖,都有提高空間。若是你能經過工具減小一個或多個環節,帶來的價值更大。



單拿其中的【開發】環節展開,就有不少可擴展的場景:



一個有表明性的例子是,咱們開發了國際化工具 kiwi【7】。它一樣具備 TS 的類型完美,很是強大的文案提示,另外還有:

  1. VS Code 插件 kiwi linter【8】,自動對中文文案標紅,若是已有翻譯文案能自動完成替換;
  2. Shell 命令全量檢查出沒有翻譯的文案,批量提交給翻譯人員;
  3. Codemod 腳本自動實現舊的國際化方案向 Kiwi 遷移,成本極低。

除了以上三點,將來還計劃開發瀏覽器插件來檢查漏翻文案,利用 Husky 在 git 提交前對漏翻文案自動作機器翻譯等等。

將來若是你只提供一個代碼庫,那它的價值會很是侷限。你能夠參照上面的圖表,開發相應的擴展來豐富生態。若是你是新手,推薦學習下編譯原理和對應的擴展開發規範。

5、嚴格完全的 Code Review

過去的一年,咱們一共進行了 1200+ 屢次 Code Review(CR),不少同事從剛開始很差意思提 MR(GitLab Merge Request,Code Review 的一種方式) 到後來追着別人 Review,CR 成爲每一個人的習慣。經過 CR 讓項目中任何一行代碼都至少被兩人觸達過,減小了絕大多數的低級錯誤,提高了代碼質量,這也是幫助新人成長最快的方式之一。


[其中一個項目MR截圖]


Code Review 的幾個技巧:

  • No magic;
  • Explicit not implicit;
  • 覆蓋度比深度重要,覆蓋度追求100%;
  • 頻率比儀式感重要,坐公交蹲廁所打開手機均可以 Review 別人代碼,不須要專門組織會議;
  • 粒度要儘量小,一個組件一個方法都可,能夠結合 Git Flow;
  • 24h 小時內處理,無問題直接 merge,有問題必定要留 comment,而且提供 action;
  • 對於亟待上線來不及 Review 的代碼,能夠先合併上線,上線後再補充 Review;
  • 須要自上而下的推進,具備完善的規範,同時按期總結 Review 經驗來豐富開發規範;
  • CR 並不僅是爲了找錯,看到好的代碼,不要吝嗇你的讚美;
  • 本質是鼓勵開發者間更多的溝通,互相學習,營造技術文化氛圍。

總結

以上5點固然不是咱們技術的所有。除此以外咱們還實踐了移動端開發、可視化圖表/WebGL、Web Worker、GraphQL、性能優化等等,但這些還停留在術的層面,將來到必定程度會拿出來分享。

若是你也準備或正在開發複雜的前端應用,同時團隊人員多樣技術背景各異,能夠參考以上5點,使用 Redux 實現規範清晰可預測的狀態管理,深耕 TypeScript 來提高代碼健壯性和可維護性,藉助各類 Lint 工具迴歸簡單方便的 CSS,不斷打磨本身的開發工具來保證開發規範高效,並嚴格完全實行 Code Review 促進人的交流和提高。

總結

本篇文章主要介紹了現代IM系統中消息系統所須要具有的能力,對比了傳統架構和現代架構。爲方便接下來的深刻探討,介紹了表格存儲Tablestore推出的Timeline模型,以及在IM系統中消息存儲和消息同步模型的基本概念和策略,最後介紹了一個典型的架構設計。

分享

本人13年Java開發經驗及產品研發經驗,BAT背景,曾在多家知名企業擔任技術總監、企業方案選型首席顧問,前後從事內核開發、大型Java系統架構設計和物聯網系統架構設計開發,精通複雜業務技術方案選型、架構、核心難點攻關,對於java語言及項目有很是深刻的理解和豐富的實操經驗,熱愛前沿技術,樂於進行技術分享與技術探討。



相關文章
相關標籤/搜索