原發於知乎專欄,歡迎關注 zhuanlan.zhihu.com/p/55357377javascript
2019 農曆新年即將到來,是時候總結一下團隊過去一年的技術沉澱。過去一年咱們支撐的數據相關業務日新月異,其中兩個核心平臺級產品代碼量分別達到30+萬行和80+萬行,TS 模塊數均超過1000個,協同開發人員增長到20+人。因爲歷史緣由,開發框架同時基於 React 和 Angular,考慮到產品的複雜性、人員的短缺和技術背景各異,咱們嘗試了各類方法打磨工具體系來提高開發效率,如下是節選的5項主要方法。css
從2013年React發佈至今已近6個年頭,前端框架逐漸造成 React/Vue/Angular 三足鼎立之勢。幾年前還在爭論單向綁定和雙向綁定孰優孰劣,如今三大框架已經不約而同選擇單向綁定,雙向綁定淪爲單純的語法糖。框架間的差別愈來愈小,加上 Ant-Design/Fusion-Design/NG-ZORRO/ElementUI 組件庫的成熟,選擇任一你熟悉的框架都能高效完成業務。前端
那接下來核心問題是什麼?咱們認爲是 狀態管理。簡單應用使用組件內 State 方便快捷,但隨着應用複雜度上升,會發現數據散落在不一樣的組件,組件通訊會變得異常複雜。咱們前後嘗試過原生 Redux、分形 Fractal 的思路、自研類 Mobx 框架、Angular Service,最終認爲 Redux 依舊是複雜應用數據流處理最佳選項之一。java
慶幸的是除了 React 社區,Vue 社區有相似的 Vuex,Angular 社區有 NgRx 也提供了幾乎一樣的能力,甚至 NgRx 還能夠無縫使用 redux-devtools 來調試狀態變化。webpack
不管如何優化,始終要遵循 Redux 三原則:git
原則 | 方法 | 引起的問題 |
---|---|---|
Single source of truth | 組件 Stateless,數據來源於 Store | 如何組織 Store? |
State is read-only | 只能經過觸發 action 來改變 State | action 數量膨脹,大量樣板代碼 |
Changes are made with pure functions | Reducer 是純函數 | 反作用如何處理,大量樣板代碼 |
這三個問題咱們是經過自研 iron-redux 庫來解決,如下是背後的思考:github
如何組織 Action?web
FetchTypes
類型來自動生成對應到 3 個 action如何組織 Store/Reducer?typescript
最終咱們獲得以下扁平的狀態樹。雖龐大但有序,你能夠快速而明確的訪問任何數據。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點:
AsyncTuple
類型,就是 {data: [], loading: boolean, error: boolean}
這樣的數據結構;AsyncTuple.handleAll
處理 LOADING/SUCCESS/ERROR 這 3 種 action,handleAll 的代碼很簡單,使用 if 判斷 action.type 的後綴便可,源碼在這裏。曾經 React 和 Angular 是兩個很難調和的框架,開發中浪費了咱們大量的人力。經過使用輕量級的 iron-redux,徹底遵循 Redux 核心原則下,咱們內部 實現了除組件層之外幾乎全部代碼的複用。開發規範、工具庫達成一致,開發人員可以無縫切換,框架差別帶來的額外成本降到很低。
TypeScript 目前可謂大紅大紫,根據 2018 stateofjs,超過 50% 的使用率以及 90% 的滿意度,甚至連 Jest 也正在從 Flow 切換到 TS。若是你尚未使用,能夠考慮切換,絕對能給項目帶來很大提高。過去一年,咱們從部分使用 TS 變爲全面切換到 TS,包括咱們本身開發的工具庫等。
TS 最大的優點是它提供了強大的靜態分析能力,結合 TSLint 能對代碼作到更加嚴格的檢查約束。傳統的 EcmaScript 因爲沒有靜態類型,即便有了 ESLint 也只能作到很基本的檢查,一些 typo 問題可能線上出了 Bug 後才被發現。
下圖是一個前端應用常見的4層架構。 代碼和工具全面擁抱 TS 後,實現了從後端 API 接口到 View 組件的全鏈路靜態分析,具備了完善的代碼提示和校驗能力。
除了上面講的 iron-redux,咱們還引入 Pont 實現前端取數,它能夠自動把後端 API 映射到前端可調用的請求方法。
Pont 實現原理:(法語:橋) 是咱們研發的前端取數層框架。對接的後端 API 使用 Java Swagger,Swagger 能提供全部 API 的元信息,包括請求和響應的類型格式。Pont 解析 API 元信息生成 TS 的取數函數,這些取數函數類型完美,並掛載到 API 模塊下。最終代碼中取數效果是這樣的:
Pont 實現的效果有:
另外 iron-redux 能接收到 Pont 接口響應數據格式,並推導出整個 Redux 狀態樹的靜態類型定義,Store 中的數據完美的類型提示。效果以下:
最終 TS 讓代碼更加健壯,尤爲是對於大型項目,編譯經過幾乎就表明運行正常,也給重構增長了不少信心。
2015 年咱們就開始實踐 CSS Modules,包括後來的 styled-components 等,到 2019 年 css-in-js 方案依舊爭論不休,雖然它確實解決了一些 CSS 語言天生的問題,但同時增長了很多成本,新手不夠友好、全局樣式覆蓋成本高漲、僞類處理複雜、與AntD等組件庫結合有坑。與此同時 Sass/Less 社區也在飛速發展,尤爲是 Stylelint 的成熟,能夠經過技術約束的手段來避免 CSS 的 Bad Parts。
.home-page{ .top-nav {/**/}, .main-content{ /**/ } }
。若是有多個頂級類,可使用 Stylelint rule 檢測並給出警告。// src/styles/variables.js
module.exports = {
// 主顏色
'primary-color': '#0C4CFF',
// 出錯顏色
'error-color': '#F15533',
// 成功顏色
'success-color': '#35B34A',
};
複製代碼
// webpack.config.js
const 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('\n'),
sourceMap: true,
sourceMapContents: true
}
}
]
}
//...
複製代碼
在 scss 文件中,能夠直接引用變量
// page.scss
.button {
background: $primary-color;
}
複製代碼
2019 年,你幾乎不可能再開發出 React/Angular/Vue 級別的框架,也不必再造 Ant-Design/Fusion-Design/Ng-Zorro 這樣的輪子。難道就沒有機會了嗎?
固然有,結合你自身的產品開發流程,依舊有不少機會。下面是常規項目的開發流程圖,任何一個環節只要深挖,都有提高空間。若是你能經過工具減小一個或多個環節,帶來的價值更大。
單拿其中的【開發】環節展開,就有不少可擴展的場景:
除了以上三點,將來還計劃開發瀏覽器插件來檢查漏翻文案,利用 Husky 在 git 提交前對漏翻文案自動作機器翻譯等等。
將來若是你只提供一個代碼庫,那它的價值會很是侷限。你能夠參照上面的圖表,開發相應的擴展來豐富生態。若是你是新手,推薦學習下編譯原理和對應的擴展開發規範。
過去的一年,咱們一共進行了 1200+ 屢次 Code Review(CR),不少同事從剛開始很差意思提 MR 到後來追着別人 Review,CR 成爲每一個人的習慣。經過 CR 讓項目中任何一行代碼都至少被兩人觸達過,減小了絕大多數的低級錯誤,提高了代碼質量,這也是幫助新人成長最快的方式之一。
Code Review 的幾個技巧:
以上5點固然不是咱們技術的所有。除此以外咱們還實踐了移動端開發、可視化圖表/WebGL、Web Worker、GraphQL、性能優化等等,但這些還停留在術的層面,將來到必定程度會拿出來分享。
若是你也準備或正在開發複雜的前端應用,同時團隊人員多樣技術背景各異,能夠參考以上5點,使用 Redux 實現規範清晰可預測的狀態管理,深耕 TypeScript 來提高代碼健壯性和可維護性,藉助各類 Lint 工具迴歸簡單方便的 CSS,不斷打磨本身的開發工具來保證開發規範高效,並嚴格完全實行 Code Review 促進人的交流和提高。
Links
咱們還在招聘,歡迎郵件簡歷,來信必回。shaoyin.ssy@alibaba-inc.com