React全家桶:石墨文檔大前端技術選型分享

技術選型是個很大的話題。對於創業公司而言,為了適應業務節奏,「靈活」與「高開發效率」是技術選型最看重的兩點。而這兩點也是這些年前端技術井噴時期新出現的技術最注重解決的兩個問題。然而石墨文檔作為一款擁有眾多企業用戶的富前端應用,複雜的表格、文檔以及離線同步邏輯使得我們對於前端技術棧的工程化和穩定性有很高的要求,考慮到過於新的技術往往生態尚不完善以及相關的「最佳實踐」缺乏驗證,我們對於這些技術的選擇相對謹慎。石墨文檔前端團隊的所有技術選型也都是圍繞如上兩點考慮的。

技術棧的選擇

石墨文檔前端團隊既包括桌面和移動端的 Web 版前端工程師,也包括 iOS 和 Android 的 App 的開發者。下面分幾塊來介紹石墨文檔前端團隊目前使用的技術棧。

網站:React

石墨文檔是一個支持多人實時協作的在線辦公平台,用戶可以在上面寫作、製表、實時分享和討論。如圖一所示,整個網頁版相對而言業務專一但卻非常複雜。石墨文檔網頁版在 2015 年前是一個基於 jQuery 構建的非單頁應用,用戶的每一次點擊都需要重新載入整個頁面,體驗非常不好。而且 jQuery 這樣的類庫抽象層次比較低,複雜度隨著代碼量增加呈指數式上升,不適合構建大型項目,所以我們決定引入一個框架來解決這些問題。

圖一 石墨文檔的桌面目前是一個單頁應用

三國鼎立的框架版圖

在當時 JavaScript 前端框架呈現出了三國鼎立的態勢:Angular, React 和 Vue 雖然各自發展的態勢不同,但是卻都牢牢佔據著主流地位。所以我們希望從這三個框架中選擇出未來石墨文檔網頁版前端技術棧的核心,使得在提高開發效率和降低維護成本的同時,也能夠保證新的技術棧在未來一段時間相對流行和易於招聘優秀人才。

Angular 在這三個當中應用得最為廣泛,團隊中也有幾個人有過 Angular 開發經驗。但經過仔細分析,Angular 1 已經能嗅出一點衰落的味道了,而且 Angular 2 的前景尚不明朗。相比而言,處在上升期的 Vue 雖然表現出了不錯的潛力,但在那時生態仍然顯得不夠成熟,選擇其作為網頁版的核心框架非常冒險。所以既具有不錯的潛力,社區也相對活躍的 React 成為了我們最後的選擇。另外當時 React Native 已經發布,相關的生態圈也在飛速發展逐漸繁榮,這成為選型天平上傾向 React 的一個不算輕的砝碼。

React 帶來的變化

相對於 Angular 和 Vue 而言,React 對於 JavaScript 工程師的水平要求更高一些。尤其是在大型項目中,對 React 不熟悉的情況下很容易寫出難以維護或性能低下的代碼。我們在遷移到 React 的初期,由於團隊只有少數幾個人接觸過這個框架,所以經歷了一段時間的「陣痛」,例如對於 shouldComponentUpdate 的錯誤使用使得一些錯誤變得不易追蹤調試。不過隨著大家的不斷實踐,React 逐漸給項目的開發帶來了非常積極的影響。開發新功能的效率得到了顯著的提高,同時憑藉組件化,團隊之間的分工更加明確,代碼也更加利於維護。

移動端:React Native

在 2015 年團隊決定全面轉向 React 時,恰巧 React Native 剛剛發布。雖然 React Native 並不是我們選擇使用 React 的最終原因,但是其也為之後移動端的技術選型和石墨文檔前端團隊的構建思路埋下了一個伏筆。

從原生到 React Native

2016 年,我們的 iOS 和 Android App 均是使用原生語言(Swift 和 Java)開發的,隨著用戶量的逐漸增多,用戶對 App 的功能需求也越來越多,其中之一就是離線支持。離線支持對於石墨文檔的場景來說是一個非常複雜的功能,需要處理離線時多層級文件結構的移動、創建、刪除以及許可權的同步問題。討論技術方案時發現如果在每個平台(包括我們的網站)重新實現一遍的話成本非常高。

當時我們正好在做移動端 App 的新版產品設計,涉及到的產品改動很多,恰好此時後端也在進行數據介面化的重構,同樣依賴移動端不少的改動。於是我們想到了趁此機會使用 React Native 對現有 App 進行重建的方案並立即開始了調研。調研的結果非常樂觀,雖然當時很多人聲稱 React Native 有很多坑,但是我們也看到了一些激動人心的成功案例。考慮到當時整個前端團隊的技術積累都在 React 棧中,而且我們的移動端 App 開發工程師也有不錯的前端基礎,所以最終決定將移動端徹底轉向 React Native。

React Native 的是與非

目前使用 React Native 開發的石墨文檔 iOS 版已經上線三個月了,而相應的 Android 版也已經發布了一個月。在這段不算長的時間中,我們收到了非常多來自用戶的積極反饋。作為石墨文檔的重度用戶,我們自己平時寫技術文檔、閱讀和評論產品需求時經常會用到石墨文檔移動端 App,實際體驗而言使用 React Native 開發的版本在流暢度方面並不弱於之前的原生 App,至少正常使用的情況下性能差異並不會讓用戶察覺到。

圖二 引入 React Native 後的 iOS 和 Android 平台實現了代碼復用

對於 React Native 的坑,由於之前技術調研時聽得太多,實際開發起來反而比預想中的順利。總結下來主要存在兩個問題:一個是性能問題。舉例來說,導航部分之前我們用的是 NavigationExperimental,在最近的一次重構中,我們 fork 了 react-navigation 在原有功能的基礎上加了一些拓展,以適應我們較為複雜的導航需求。重構之後在大多數機型里表現得很流暢,但是在一些低端安卓機上性能和原生組件相比還是存在不易被忽略的差異。這個組件目前已經開源在我們的 GitHub 上:

github.com/shimohq/shim

我們遇到的另一個性能問題是列表組件引起的,官方提供的 ListView 和 FlatList 在大數據量的情況下(如圖二中桌面上的文件列表條目有時會比較多)容易成為性能瓶頸。為此現在的文件列表是使用原生代碼開發的,後面我們馬上會做一個通用的原生端模板式渲染組件來對列表進行渲染。不過總體來說 React Native 的性能還是令人滿意的,對於一些比較慢的地方也能夠有針對性地進行優化。

除了性能問題,另一個就是進行第三方 SDK 對接時,往往對方不會提供 React Native 介面。這時就需要我們這邊進行一些橋接工作。這個過程本身並不複雜,不過如果 React Native 工程師完全沒有原生開發經驗的話還是會有一些吃力。因此在團隊構成方面,雖然我們不再需要專職的 iOS 和 Android 開發工程師,所有新的業務功能都可以由 JavaScript 工程師實現,但是我們在招聘時仍然更青睞有原生應用開發背景的 React 工程師。目前我們移動客戶端組的不少工程師都是既擅長 React/Redux,也掌握 iOS 或 Android 平台上的原生開發知識。

打包工具:Webpack & Rollup

石墨文檔主站的打包是通過 Webpack 實現的。Webpack 提供了強大的一站式解決方案,使得 JavaScript、CSS 和圖片等靜態資源可以通過簡單的配置實現需要的整合或拆分打包效果。

一些獨立的內部類庫則使用了 Rollup 進行打包,Rollup 支持了 Scope hoisting,生成的代碼可讀性明顯好一些,更重要的是其能生成體積更小的代碼包以及更快(雖然可以忽略不計)的運行速度。不過相對於 Webpack 而言,Rollup 在一些地方(尤其是開發調試方面)仍有欠缺,使得 Webpack 仍將是我們新項目的默認選擇。

另外我們也在持續關注 Facebook 前段時間發布的 Prepack,一款 JavaScript 代碼優化工具。通過在幾個內部項目中進行的實驗,能夠看出其在特定代碼片段可以起到不錯的提升作用。不過由於其仍在早期開發過程中,我們並沒有在生產環境中使用。

代碼規範:Standard

要提升一個團隊的產出效率,就要改善團隊的協作方式。統一代碼規範能夠大大提升團隊內部的代碼交流效率。在一個團隊中,不同的工程師會有不同的編碼偏好,如經典的 JavaScript 到底要不要寫分號的問題。實際上這些代碼風格的爭論並沒有多少意義,真正有意義的則是確定並嚴格執行一套統一的代碼風格。統一代碼風格能夠顯著提升團隊內部每個人的代碼理解速度,從而實現高效 Code Review。多個人協作同一個項目時也不會出現因為修改代碼風格而發起的無意義的 Pull Request。

在石墨文檔,我們使用了 standard 作為基準規範。Standard 的理念在於不可配置,停止爭論。其規定了一系列代碼規範,比如代碼不加分號、統一使用單引號包裹字元串等。之所以使用 standard 作為基準規範而不是直接使用其作為 lint 工具是因為 standard 對於特定的規則並沒有做更嚴格的要求,如大括弧內部是否需要空格符等,所以我們基於 standard 的規則定義了一系列額外規則,旨在能夠讓團隊的每個人在理解代碼時不會被代碼風格的細微差異引入的噪音所干擾。當然在指定這些額外規則時,我們約定了「制定的新規則不能和 standard 的規則衝突」,這使得我們不會陷入制定代碼風格的無止盡的討論中。

技術棧與團隊構建

技術棧與團隊構建是相互影響的。技術選型造就了團隊的職能結構,而反過來團隊的具體情況也會對技術選型提出不同的要求。

在擁抱 React 之前,當開發任何新功能時,需要至少三名研發(即網站前端、iOS 工程師和 Android 工程師)參與進來。其中每個人對需求的理解可能都會有一些偏差,導致比較高的溝通成本。而使用 React 之後,由於這三個主要平台使用的都是同樣的技術棧,大量的代碼得以復用和共享,我們得以探索新的團隊構建模式。目前石墨文檔前端團隊正在逐步向跨平台團隊轉變,具體而言即每個產品需求由同一個前端工程師來完成,這名工程師會負責這個需求的網頁版、iOS 和 Android 版的開發。這樣無論是前期需求討論,還是開發完成後的確認與 QA 流程,效率都能大幅度提升。

而隨著石墨文檔前端團隊的迅速發展,我們也一直在思考如何能夠通過技術選型來更加適應團隊的當前情況。除了上文提到了使用 standard 來統一團隊代碼規範外,TypeScript 也是我們正在調研的技術方向。相比於 JavaScript,TypeScript 的靜態類型更適合構建大型的應用,這正是其吸引我們的地方。

作者介紹:李子驊,石墨文檔技術總監

原 文:前端之巔

作 者:李子驊

更多技術文章和開發者工具,SDK,API請查看:SDK.CN - 中國領先的開發者服務平台


推薦閱讀:

哈佛商業評論 x 場景實驗室 | 石墨文檔獲評「 年度管理服務產品 」
提高團隊效率,石墨文檔上線一站式解決方案
你還在「窮忙」嗎?何不試試極簡主義
互聯網金融團隊提高效率的辦公利器
石墨文檔的雲端表格實時壓縮策略

TAG:前端开发 | 技术选型 | 石墨文档 |