著作權歸作者所有。商業轉載請聯絡 Scott 獲得授權,非商業轉載請註明出處[務必保留全文,勿做刪減]。
Scott 近兩年無論是面試還是線下線上的技術分享,遇到許許多多前端同學,由於團隊原因,個人原因,職業成長,技術方向,甚至家庭等等原因,在理想國與現實之間,在放棄與堅守之間,搖擺不停,心酸硬抗,大家可以找我聊聊南聊聊北,對工程師的宿命有更多的瞭解,有更多的看見與聽見,Scott 微信: codingdream。
本系列共 15 篇,此為第二篇,大家看完轉發下朋友圈我就心滿意足了。
任何可以用 JavaScript 來寫的應用,最終都將用 JavaScript 來寫。 -- 阿特伍德定律
這篇文章向大家介紹下小菜前端的基建在一步步走過來的過程中,NodeJS 是如何使用的及扮演了哪些角色,它對於工程師個人,團隊能力,公司研發效率,業務支撐,技術的探索與突破等等到底有什麼實際的意義,以及為什麼是它而不是 Python/C++/PHP/Java 成為了前端團隊的核心技術棧。
被 NodeJS 加速的框架演進速度
2019 年的前端與 2009 年的前端早已是君住長江頭我住長江尾,短短十年,人是物非,React/Vue 一統天下,Webpack 標配江湖,單純看近 2 年的 【Npm Trends】:
或者參考近 10 年的【Google Trends】:
熱度一定程度反映了社群活躍,和佔用市場的體量,可以發現 AngularJS 也是經歷了過山車,市場被 React/Vue 不斷侵蝕,那再把 jQuery 加進來看下:
令人瞠目結舌,即便 React/Vue(綠色和紫色) 如日中天的今天,在整個網路的搜尋熱度上,也遠遠低於 jQuery 和 NodeJS,尤其是 jQuery,雖然它的熱度在持續降低,但依然是整個網際網路中不能忽視的重要組成部分,
雖然早期與 jQuery 同時代還有很多其他框架類庫,比如 ExtJS/Mooltools/Dojo/Yui/Kissy 等等等等,但它們的體量比起 jQuery 都差之甚遠不再比較,如果大家把近十年聽到的看到的框架羅列起來,幾十上百都不成問題,生命週期能超過 5 年卻寥寥無幾,尤其是在 2012 年 NodeJS 在全球推廣到一定規模後,框架的誕生迭代替換更為快速,所以從框架的生命力來看,jQuery 目前為止依然是贏家,那它跟 NodeJS 有什麼關係呢?
NodeJS 的持續變熱,jQuery 也在持續走冷,一部分原因就是 NodeJS 生態基建能力,在之上不斷的生長出來新的框架與解決方案(不限於 AngularJS/React/Vue),也在不斷的蠶食 jQuery 的市場,倘若沒有 NodeJS,自然也不可能有新框架的繁榮之態,今天大有可能依然是 jQuery 在一統江湖。
在今天,無論是 Angular/React/Vue/Webpack,從開發體驗、單元測試到打包編譯,脫離了 NodeJS 生態,都無法正常運轉,NodeJS 就是整個上層建築的物理基礎和配套設施,我們從巨集觀上了解了 NodeJS 對於前端框架進化和保障的重要性。
接下來,就結合小菜前端在 NodeJS 上的建設與大家聊聊它的重要性,2 年來,我們重度使用 NodeJS 陸續參與了十幾個重要的工具/產品/系統的建設,下面挑選四個有代表性的分享給大家:
小菜前端第一次嚐鮮 NodeJS - APP 熱更新服務
寫一些 NodeJS 自動化指令碼,程式碼校驗甚至利用 Express/Koa 搭建一些簡單的服務,這些都不能算做真正意義使用 NodeJS,我們也拋開 ReactNative/Webpack 等前端開發打包編譯需要依賴 NodeJS 這樣的場景,我們第一次真正意義使用 NodeJS, 就是對 ReactNative APP 開發的熱更新系統,代號神奇博士,服務端框架用的 ThinkJS 框架,那時候是 2016 年中,Scott 還沒有入職小菜。
這樣一個熱更新發布系統可以讓客戶端 APP 動態更新到增量的程式碼包,最原始的更新流程如下圖:
在熱更新系統中,需要針對 iOS/Android 的 IPA/APK 包進行特定作業系統的資源拆包,增量包/原生包儲存,包版本管理,許可權管理等功能,這些事情是不太可能讓服務端童鞋比如 Java 童鞋替你做的,只能前端自己做,也只能用 NodeJS 才能快速的開發出來。
系統上線後,整個公司的 App 發版頻率從一個月一兩次(稽核還會被打回)提升到一週三四次,效率至少提升 10 倍,而且使用者的更新體驗得到質的提升,對於業務/運營/產品/使用者都有極大的價值。
這時候我們概念裡面的 NodeJS 可能更像是一個特定場景的功能玩具,並沒有深挖它的重要性和可能性,雖然嚐到了甜頭,但往後的一年多沒有再持續挖掘。
小菜前端第二次嚐鮮 NodeJS - APP 打包平臺
Scott 是從 2011 年開始接觸和使用 NodeJS,從 2013 年後技術棧以 NodeJS 為主,開始嘗試搭建比較複雜的系統,非常清楚它的優勢和短板,在 2017 年下半年開始帶前端團隊的時候,收到了很多的反饋和投訴,主要分為兩類: APP 更新失敗的問題(在非常高的迭代節奏下) 和前後端協作的介面/聯調問題,針對 APP 更新下失敗的問題,我們先來還原下當時的開發狀態,大家如果也有多人協作 RN APP 的開發,可以參考接下來我們的做法,相信對你有用。
我們的 APP 當時一共有 5 個 - 宋小菜(對外)、宋小菜司機(對外)、宋小菜供應商(對外),宋小福(對內)、採祕(對內),所有的 APP 都是 RN 開發,都有 iOS/Android 兩個版本,其中對外的是商業開發版本,要釋出到蘋果商店和推送到特定渠道,對內的都是企業包,不對外公開,我們通過公司自己的網站託管應用供員工安裝。
這些 APP 之間的業務也有一定的聯絡,通常開發宋小菜,也會聯動要修改宋小福或者採祕,在本地開發的時候,需要在每個包裡面,區分連線的是日常測試環境,還是線上生產環境,還要區分是可以列印出日誌的 debug 包,還是非 debug 包,並且最終上線前,再由每個同學在本地 Mac 上打出一個包上傳到熱更新平臺,這個流程裡面會出現大量問題,我曾經畫了這樣一張圖給服務端的同學解釋為什麼前端打包 APP 到上線會經常出問題:
這樣就會有很多組合,有的包是要頻繁打的,有的偶爾來幾發,打包的時候要區分:
- 是哪一個 APP
- 是打 iOS 還是 Android 的包
- 是正式環境,還是日常測試環境
- 打的包要不要開啟熱更新功能,不開啟就不會走線上熱更新流程
- 這個包要不要實時連到本地打一些 log 出來,也就是是否 Debug
- 是在哪個同學電腦上打的包
這樣硬組合就可以打出 64 個不同的包,意味著可能需要把配置檔案修改 64 次,另外,每個同學電腦上的 Mac 作業系統版本會有不同,XCode/Gradle 也可能版本不同,更不用說 Node 以及 NPM 所安裝的三方包,甚至本地預裝的開發者證照也時有不一致的情況,於是整個團隊陷在了打包/包正確性/一致性/是否能打出來一堆問題形成的泥坑裡,艱難的對外解釋,艱難的互相配合,針對這個問題,我們思路是讓這一切可以傻瓜一點自動化,讓團隊共用一個打包環境,以它打的包為準,於是我們啟動了大伯伯打包平臺,採購了一臺高配 Mac Mini 部署在內網,把所有的配置項都通過介面來管理,簡要流程如下:
介面一開始很樸素,長這個樣子:
這個系統上線 1 年來,我們已經打了 1000 多個包,因為打包而出現環境錯誤問題 0 次,極大的解放了團隊效率和提升打包的正確性,更重要的是對於團隊也沉澱了一些基於 Node 使用的技能,堅定了大家使用它的信心:
小菜前端第三次嚐鮮 NodeJS - 報表快速製作平臺
無論是 toB 還是 toC 公司,把資料庫裡的資料拎出來,無論直接匯出為 Excel,還是通過介面輸出到前端頁面中展示,都是硬剛需,小菜也不例外,而且小菜的業務早些年變化特別高頻,每次變化都要提一堆報表需求來監控調整前後的業務變化是否符合預期,如果沒有了報表就跟算命一樣全靠猜,然後這樣一個普通不能再普通的需求,卻讓小菜整個產品技術團隊頭疼了好幾年。
在緊張的業務開發專案中,讓前後端各自抽出資源來對接一個個的報表欄位,再通過介面 - 頁面的聯調和釋出,是一件非常浪費資源的事情,後端感覺自己像是一個寫 SQL 的和介面膠水程式碼的,前端感覺自己就是個純粹 Table 報表頁面仔,而且經常資源交叉衝突導致報表優先順序降低甚至拖很久不能給到業務方,所以公司做了整整 3 年,總共才產出了 50 多個報表零散的扔在 ERP 系統裡面,針對這個問題,前端啟動了一個專案 - 大表哥報表平臺,用來解決報表產出效率的問題,實現 SQL 到頁面的自動生成,後端工程師,甚至會 SQL 的產品經理和運營都可以到平臺上,按照約定的規則貼上一些 SQL,或者基於編輯頁面組裝一些 SQL 的子語句,咔咔!報表生成,這個系統上線 1 年來,生產力一下子得到釋放,總共產出了 400 多張報表:
公司的員工瀏覽報表每天都有一兩千次,直接匯出 Excel 就匯出了 1 萬 6 千多次,已經是公司內部最成功的一個工具產品,服務於全公司所有部門,報表展示大概長這樣:
一個報表的製作介面大概長這樣:
通過對 SQL 的各種查詢詞的元件封裝,可以從介面快速生成一個可在資料庫執行的複雜 SQL 語句,或者反向貼入符合規則的 SQL,自動拆解成報表的表頭(欄位的中文名稱),自動對映到元件(日期、排序、篩選、二級跳轉的子報表等等),包括整個報表的需求提出、描述、認領、上下線、製作和釋出這樣的工作流等等也全部用 NodeJS 實現,這次嚐鮮不僅奠定了 NodeJS 在前端團隊絕對的位置,也實質性的在支撐業務這裡拿到很好的結果,更讓我們感到欣喜的是,在報表系統裡面使用 GraphQL 是多麼的便捷,同時前端部門獨立支撐資料相關的業務產品這條路變得可行,NodeJS 的角色從工具也延展到了業務。
小菜前端第四次嚐鮮 NodeJS - 前後端資料聚合服務
如果說前面幾個,都是與服務端團隊解耦的,是前端可以獨立完成的,那麼這一次,則是跟服務端在職能上和系統上都有強耦合的地方,是跨團隊研發層面的嘗試,這次發生在 2018 年 2 月份,也就是在前兩次嚐鮮後,我們又一次比較大膽的突破。
背景依然是前端的頁面與後端的介面這裡,關於這個後面會專門有一篇詳細與大家聊聊前後端合作研發上我們的思考,這裡我簡述一下,前後端的合作方式通常是資料介面,也就是資料格式和欄位約定,一個吐資料一個消費資料,吐什麼樣的資料取決於消費什麼樣的資料,消費的資料則來源於產品流程上的 UI 展示形式,一份概念裡統一的資料,是有可能被分拆成兩個 UI 塊展示和複用,可能會讓介面顆粒度更小拆成 2 個,或者共用一個大的,頻次高一些的 UI 改版也會導致介面的通用性變得很弱,最終產生一堆大而全的重體積介面,進而對前端維護頁面和使用者的載入產生較大的影響。
而且介面裡面永遠是黑盒,在前端是看不全介面的能力了,一旦文件沒有跟上,介面的輸出與 UI 的使用便會脫節,為產品執行的帶來了更強的不穩定性,所以我們會希望介面都是純粹的,用到多少欄位就輸出多少欄位,用到什麼格式就輸出什麼格式,同一個頁面的資料,儘量一個介面返回而不是三四個介面返回,但這顯然對服務端提出了更高的要求,也是很多公司從前端產品層面試圖推動後端團隊時候無功而返的最大阻力。一個人群中,大部分人都傾向於不作出改變,在沒有看到太多對自己帶來的好處之前,而短期成本與長期紅利之間大部分會選擇短期,因為它容易預見。
我們的解決辦法是,用 NodeJS(EggJS) + GraphQL 搭建一個系統,它負責三件事:
- 負責對前端輸出所需資料(單介面,要什麼給什麼,無冗餘可組合)
- 負責去拿所有的服務端微服務介面資料(HTTP 協議或者 RPC 協議)
- 提供一個可以線上連線介面、約束欄位以及實時 Mock 的編輯系統
對它的要求是可線上編輯,可聯調測試,可資料熱釋出與熱回滾,這個系統上線後,我們接管了 2 款 App 的介面需求,前端拼裝頁面和組合資料時候變得更靈活自如,同時正向逆向的資料監控,讓我們對資料更有把控力,對於服務端來說,也可以更加不關注 UI 如何,更關注業務領域的搭建與標準資料介面的封裝,它的介面長這個樣子:
還有介面地圖、資料關係網路、介面欄位監控、Mock 系統等等不再一一截圖,這個 NodeJS 搭建的系統的複雜度還是蠻高的,上線後我們專門組織了一場技術分享 - 杭州第一屆 GraphQLParty,讓它開源的群眾呼聲很高,我們覺得還需要更多 NodeJS 的專家進來把系統進一步完善後,才真正能達到開源的標準,目前依然是在公司內部使用。
綜上,小菜前端基於 NodeJS 既有 Eat Your Own Shit 的內部場景的問題解決,也有直接服務於前端產品的工具,也有直接把資料當做業務來支撐公司決策的業務產品,還有專注在前後端研發效率的資料聚合層的全方位嘗試,從內到外從前到後,而這些系統的嘗試,又為前端團隊沉澱了非常多的服務端能力,系統設計能力,甚至帶來跨語言棧的變化,童鞋們的技術能力也都大幅提升,所以 NodeJS 越來越成為前端團隊的核心技術棧,目前第五次大規模的 NodeJS 使用我們聚焦的是運維健康體系的搭建,相信在你的團隊,基於它做深度使用,只要能貼合你團隊的痛點,公司業務的痛點,解決掉問題帶來價值,那麼這些嘗試或者說試錯都是值得肯定和鼓勵的。
最最後,本文作為預熱篇,旨在針對如下話題為大家輸出:
- 把團隊蠻荒到自動化運維的從 0 到 1
- 成長曆程總結輸出給社群,幫助更多的小團隊少走彎路
- 以一種可被量化的方式匯聚小菜前端的困惑、沉澱與方法路徑,給團隊帶來更多創作成就感
- 從更多視角側切進入團隊管理/技術演進/個人成長的過程中,探討工程師團隊的價值最大化
如果大家感興趣,我們小菜前端團隊,會集體智慧共同凝聚,一起撰寫並推出一本偏前端職業生涯、技術成長和團隊成長的小冊,回饋給大家,大家在文後記得留言評論和提需求哦,還有別忘了加 Scott 微信哈: codingdream。