鼎信諾審計前端取數工具_給2019前端的5個建議

2019 農歷新年即將到來,是時候總結一下團隊過去一年的技術沉淀。過去一年我們支撐的數據相關業務突飛猛進,其中兩個核心平臺級產品代碼量分別達到30+萬行和80+萬行,TS 模塊數均超過1000個,協同開發人員增加到20+人。由于歷史原因,開發框架同時基于 React 和 Angular,考慮到產品的復雜性、人員的短缺和技術背景各異,我們嘗試了各種方法打磨工具體系來提升開發效率,以下是節選的5項主要方法。

一、基于 Redux 的狀態管理

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

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

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

9ccb01e70d6f79e48b9cd9e0b95852b7.png

無論如何優化,始終要遵循 Redux 三原則:

原則 方法 引發的問題 Single source of truth 組件 Stateless,數據來源于 Store 如何組織 Store? State is read-only 只能通過觸發 action 來改變 State action 數量膨脹,大量樣板代碼 Changes are made with pure functions Reducer 是純函數 副作用如何處理,大量樣板代碼 這三個問題我們是通過自研 iron-redux 庫來解決,以下是背后的思考:

如何組織 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層

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

8d1749dc96931368230b61196c041ccf.gif

[Redux 狀態樹]如何減少樣板代碼? 使用原生 Redux,一個常見的請求處理如下。非常冗余,這是 Redux 被很多人詬病的原因。

const initialState = { loading = true, error = false, data = []};function todoApp(state = initialState, action) { switch (action.type) { case DATA_LOADING: return { ...state, loading: true, error: false } case DATA_SUCCESS: return { ...state, loading: false, data: action.payload } case DATA_ERROR: return { ...state, loading: false, error: true } default: return state }}

使用 iron-redux 后:

class InitialState { data = new AsyncTuple(true);}function reducer(state = new InitialState(), action) { switch (action.type) { /** 省略其它 action 處理 */ default: return AsyncTuple.handleAll(prefix, state, action); }}

代碼量減少三分之二!!

主要做了這2點:

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

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

二、全面擁抱 TypeScript

TypeScript 目前可謂大紅大紫,根據 2018 stateofjs,超過 50% 的使用率以及 90% 的滿意度,甚至連 Jest 也正在從 Flow 切換到 TS。如果你還沒有使用,可以考慮切換,絕對能給項目帶來很大提升。過去一年,我們從部分使用 TS 變為全面切換到 TS,包括我們自己開發的工具庫等。

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

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

55680903fd98687375fa8e8dd949a4bd.png

[前后端協作簡圖]除了上面講的 iron-redux,我們還引入 Pont 實現前端取數,它可以自動把后端 API 映射到前端可調用的請求方法。

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

0ae4a85643a839076bab59b3c7a77a0f.png

Pont 實現的效果有:

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

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

7ed8f46c05946ffcea1dbae8c6d61480.png

最終 TS 讓代碼更加健壯,尤其是對于大型項目,編譯通過幾乎就代表運行正常,也給重構增加了很多信心

三、回歸 Sass/Less

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

  1. 全局污染:約定每個樣式文件只能有一個頂級類,如 .home-page{ .top-nav {/**/}, .main-content{ /**/ } }。如果有多個頂級類,可以使用 Stylelint rule 檢測并給出警告。
  2. 依賴管理不徹底。借助 webpack 的 css-loader,已夠用。
  3. JS 和 CSS 變量共享。關于 JS 和 Sass/Less 變量共享,我們摸索出了自己的解法:
// src/styles/variables.jsmodule.exports = { // 主顏色 'primary-color': '#0C4CFF', // 出錯顏色 'error-color': '#F15533', // 成功顏色 'success-color': '#35B34A',};// webpack.config.jsconst styleVariables = require('src/styles/variables');// ... { test: /.scss$/, use: [ 'style-loader', 'css-loader?sourceMap&minimize', { loader: 'sass-loader', options: { data: Object.keys(styleVariables) .map(key => `$${key}: ${styleVariables[key]};`) .join(''), sourceMap: true, sourceMapContents: true } } ] }//...

在 scss 文件中,可以直接引用變量

// page.scss.button { background: $primary-color;}

四、開發工具覆蓋全鏈路

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

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

fd1ab11b667655cccb516fd456772cfc.png

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

f1d1ae08f3ca394ece6c22723c866c15.png
  1. 一個有代表性的例子是,我們開發了國際化工具 kiwi。它同樣具有 TS 的類型完美,非常強大的文案提示,另外還有:VS Code 插件 kiwi linter,自動對中文文案標紅,如果已有翻譯文案能自動完成替換
  2. Shell 命令全量檢查出沒有翻譯的文案,批量提交給翻譯人員
  3. Codemod 腳本自動實現舊的國際化方案向 Kiwi 遷移,成本極低

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

未來如果你只提供一個代碼庫,那它的價值會非常局限。你可以參照上面的圖表,開發相應的擴展來豐富生態。如果你是新手,推薦學習下編譯原理和對應的擴展開發規范。

五、嚴格徹底的 Code Review

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

fd89e35a1cf25bc984bcc6b7f98d516f.png

【其中一個項目MR截圖】Code Review 的幾個技巧:

  1. No magic
  2. Explicit not implicit
  3. 覆蓋度比深度重要,覆蓋度追求100%
  4. 頻率比儀式感重要,坐公交蹲廁所打開手機都可以 Review 別人代碼,不需要專門組織會議
  5. 粒度要盡可能小,一個組件一個方法均可,可以結合 Git Flow
  6. 24h 小時內處理,無問題直接 merge,有問題一定要留 comment,并且提供 action
  7. 對于亟待上線來不及 Review 的代碼,可以先合并上線,上線后再補充 Review
  8. 需要自上而下的推動,具有完善的規范,同時定期總結 Review 經驗來豐富開發規范
  9. CR 并不只是為了找錯,看到好的代碼,不要吝嗇你的贊美
  10. 本質是鼓勵開發者間更多的溝通,互相學習,營造技術文化氛圍

總結

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

如果你也準備或正在開發復雜的前端應用,同時團隊人員多樣技術背景各異,可以參考以上5點,使用 Redux 實現規范清晰可預測的狀態管理,深耕 TypeScript 來提升代碼健壯性和可維護性,借助各種 Lint 工具回歸簡單方便的 CSS,不斷打磨自己的開發工具來保證開發規范高效,并嚴格徹底實行 Code Review 促進人的交流和提升。

作者:前端新能源

鏈接:https://juejin.im/post/5c617c576fb9a049e93d33a4

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/539358.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/539358.shtml
英文地址,請注明出處:http://en.pswp.cn/news/539358.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Hadoop HA

HA概念: high avalability 高可用性。 hadoop 1.x非ha設計 Secondnode對元數據的可靠性有了保障,但服務的可用性不高。 即:當Namenode節點宕機了,整個hadoop就不能使用了,影響了client的使用。 hadoop 2.x的ha設計 新…

紫光展銳處理器有那些手機用_酷派將發千元5G手機,國產紫光展銳加持,主打性價比...

↑↑↑點擊上方藍字訂閱每日最新熱點手機資訊數年之前,“中華酷聯”是國產智能手機的四大代表。不過隨著越來越多的強力競爭者入局,中興、酷派、聯想漸漸衰敗,僅剩華為屹立手機行業頂端。但是酷派似乎從未想過放棄,最近便要發布一…

jelly bean android,Jelly Bean占Android系統份額突破10%

Android系統份額圖(騰訊科技配圖)騰訊科技訊(清雨)北京時間1月4日消息,據國外媒體報道,微博)周四發布最新數據顯示,Android 4.1版本和Android 4.2版本的Jelly Bean在Android系統中的份額超過了10%,另外Android 4.0版本的ICS的份額…

Unable to load native-hadoop library for your platform

警告: 16/08/04 19:21:36 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable 原因: 沒有配置好環境變量,hadoop的native沒有配置進去 解決方法&#x…

android網絡切換socket,Android版的websocket切換網絡無法重連

- 當前 Bug 的表現(可附上截圖)1、android微信使用websocket切換網絡時一般都無法重連,有時候重啟微信也沒用,需要重啟手機才能連上。移動或聯通網絡切換到電信網絡特別容易出現。2、Android微信使用socketIO經常會斷線重連,有時候斷線幾次就…

妲己機器人需要什么條件才能使用_estar零封YTG:平頭哥快樂電競,只有妲己沒亞瑟,差評...

2020KPL秋季賽常規賽第8周最后1個比賽日的第2場比賽,結果已經塵埃落定了。而最終的比賽結果是:estarpro輕松以3比0的大比分零封戰勝YTG。有一說一,這一場比賽真的是毫無懸念啊,甚至雙方交手的第1小局比賽,estarpro只用…

藍橋杯 出現次數最多的整數

問題描述   編寫一個程序,讀入一組整數,這組整數是按照從小到大的順序排列的,它們的個數N也是由用戶輸入的,最多不會超過20。然后程序將對這個數組進行統計,把出現次數最多的那個數組元素值打印出來。如果有兩個元素…

python離線錄音轉文字_Python將文字轉成語音并讀出來的實例詳解

前言 本篇文章主要介紹,如何利用Python來實現將文字轉成語音。將文字轉成語音主要有兩種不同的實現方法:先將文字轉成語音,然后再通過讀取語音實現發音、直接調用系統內置的語音引擎實現發音,后一種方法的實現主要利用第三方庫。 …

Linux 文件夾權限

文件夾默認權限:drwxr-xr-x 755 文件默認權限:-rw-r--r-- 644 ------------------------------------------ drwxr-xr-x 第一位(左數)表示當前目錄是目錄還是文件,d表示目錄,-表示普通文件. 后面9位分為3組,每3組作為1組, 從左到右分別表示&…

魅族15系統是android,魅族15系列評測:性能夠用王者榮耀優化

硬件性能:中配夠用,高配優秀硬件方面,文章前面的參數表已經寫得很清楚,魅族15搭載的是高通驍龍660處理器,并配備4GB的運行內存;魅族15 Plus則搭載三星Exynos 8895,配備6GB運行內存。在目前的移動…

.net 怎么循環得到數組里的值_HashMap 底層實現、加載因子、容量值及死循環

寫在前面:2020年面試必備的Java后端進階面試題總結了一份復習指南在Github上,內容詳細,圖文并茂,有需要學習的朋友可以Star一下!GitHub地址:abel-max/Java-Study-NoteHashMap 簡介HashMap 是一個基于哈希表…

Linux下 -bash: php: command not found 命令找不到

轉載自CSDN博客,原作者:warthur。原文鏈接:http://blog.csdn.net/warthur/article/details/47342163這個問題其實很簡單,如果你在終端輸入一個命令,而系統提示你說命令沒有找到(Command not found&#xff…

hdfs命令

bin/hdfs dfs命令 appendToFile Usage: hdfs dfs -appendToFile <localsrc> ... <dst> 追加一個或者多個文件&#xff08;linux文件&#xff09; <localsrc> ...到hdfs制定文件<dst>中.也可以從命令行讀取輸入. hdfs dfs -appendToFile localfile /use…

eclipse jdk配置_eclipse的安裝和jdk的配置(JAVA)

首先需要到eclipse官網下載(eclipse.org)點擊download進入新界面點擊download 64bit進入新界面 點擊劃線的&#xff0c;點擊download也許但是比較慢&#xff0c;點擊劃線的會出現擴展選項&#xff0c;選擇距離你比較近的節點(速度比較快)作者選的是C…

webview跟html通信的原理,1.iOS: webView與html的交互

摘要:由于最近的項目中大部分功能需要 iOS 原生端與 html 進行交互才能完美實現,所以對 iOS 與 html 的交互方式進行了學習,這篇文章主要介紹 WebViewJavascriptBridge 框架的使用.至于原生的 JavaScriptCore.framework 就不多介紹了,同時在這里推薦一個比較好的博客.http://bl…

HDFS Federation(HDFS 聯盟)介紹

1. 當前HDFS架構和功能概述 我們先回顧一下HDFS功能。HDFS實際上具有兩個功能&#xff1a;命名空間管理&#xff08;Namespace management&#xff09;和塊/存儲管理服務&#xff08;block/storage management&#xff09;。 1.1 命名空間管理 HDFS的命名空間包含目錄、文件和塊…

linux java 部署 生產環境

2019獨角獸企業重金招聘Python工程師標準>>> 下載文件 首先進入網頁&#xff1a; http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 點擊Accept License Agreement后選擇jdk-8u161-linux-x64.tar.gz&#xff0c;下載。 配置環…

c#位數不夠0補充完_C# 位數不足補零

C#位數不足補零&#xff1a;int i10;方法1&#xff1a;Console.WriteLine(i.ToString("D5"));方法2&#xff1a;Console.WriteLine(i.ToString().PadLeft(5,0));//推薦方法3&#xff1a;Console.WriteLine(i.ToString("00000"));在 C# 中可以對字符串使用 …

華為鴻蒙發布作文,華為鴻蒙OS定檔6月2日發布!MatePad Pro 2或同臺亮相:首發預裝...

5月25日一早&#xff0c;原華為EMUI官微就正式宣布更名為Harmony OS&#xff0c;并宣布將在6月2日晚20點召開鴻蒙操作系統及華為全場景新品發布會&#xff0c;屆時將正式發布鴻蒙OS正式版。據近期進行開發者測試的用戶反饋&#xff0c;鴻蒙OS目前已經非常完善&#xff0c;且穩定…

python如何根據數據畫散點圖_如何用python畫出樣本的散點圖?

用python畫樣本散點圖的方法&#xff1a; 數據&#xff08;取第一列作為x&#xff0c;取第四列作為y&#xff09;如下&#xff1a;實現代碼如下&#xff1a;import matplotlib.pyplot as plt import numpy as np # 定義畫散點圖的函數 def draw_scatter(n, s): ""&qu…