天天看點

指尖前端重構(React)技術調研分析

重構前的技術文檔調研與分析,包括技術選型為什麼選擇react,應用過程中的注意事項等。

摘要:重構前的技術文檔調研與分析,包括技術選型為什麼選擇react,應用過程中的注意事項等。

一、為什麼選擇React

React是目前前端應用最廣泛的架構。三大SPA架構 Angular、React、Vue比較。

  • Angular出現最早,但其在原理上并沒有React創新的性能優化,且自身相對來說顯得笨重。
  • Vue出現最晚,其核心原理學習了React,隻是文法形式的變化,關系上來說React是開拓者,Vue是學習者。
  • React社群有強大活力與創新能力,不斷湧現革命性的創新産品,其中包括可以使用JS操作原生控件的React Native,Vue後來跟進學習出了類似的Weex,但兩者成熟度差很多。

目前來看React的生态系統要比Vue大的多,在github、stackoverflow等最大的技術社群搜尋兩者,React的搜尋結果是Vue的十倍左右,另外據近期統計使用React的站點是Vue的幾百倍以上。更大的生态意味着更多可用的資源,以及遇到問題可以得到更多的有效參考與幫助,這也是除了性能之外選擇React的核心原因。

選擇React之後,應用會在以下幾個方面有提升。

  • 第一,原先的html間跳轉會有短暫的白屏現象,這一點在安卓性能較差的機器上尤為明顯,而React作為單頁應用沒有這個問題。
  • 第二,React 提供的虛拟DOM包含Diff算法,即将原dom copy一份,與改動後的dom對比,隻渲染不同的dom節點,實作最小代價渲染,vdom創新的性能優化方式對性能的提升毋庸置疑。
  • 第三,React中核心元件化技術,更加容易的綁定事件行為,動态更新特定的dom,代碼更加子產品化,重用代碼更容易,結構清晰易維護。

二、在移動端使用React

三大架構在移動端分别有自己的東西。Angular的ionic,React的React Native,Vue的Weex。其中ionic 是基于cordova技術,依然是浏覽器應用。而後兩者已上升到操作原生控件的層面,做出來的是原生界面,其中React Native的成熟度遠高于Weex,已經被很多公司使用,而Weex使用者很少。

綜合來看選擇React 生态明顯最佳,由目前的cordova過渡為cordova+Reactjs,然後可以平滑地過渡到React Native,媲美原生性能的最優混合開發方式。之是以說平滑是因為React Native中近90%的代碼(JS)可以在IOS和Android端使用,剩餘的涉及原生的代碼也基本可以找到可用的資源,就像cordova 的插件一樣。畢竟如果需要同時掌握JS, OC(或swift),java(或kotlin)才能開發React Native的話,那這門技術不會有人用;當然反過來如果有原生開發知識的話會對開發React Native有一定幫助。

直接轉型為React native的話涉及了應用底層架構的變動,有比較大的跨度,而轉為cordova+Reactjs相對容易,而由cordova+Reactjs到React Native同樣容易不少,因為其中大部分Reactjs代碼可以重用。

三、Reactjs開發工具的選擇

首先開發腳手架官方出了Create-react-app,內建了webpack-目前最流行的打包工具,babel-提高js版本相容性的轉碼器,以及ESLint-代碼檢測工具和其它一些常用工具,同時對這些工具進行了比較優的配置。值得一提的是該腳手架将這些工具的配置檔案進行了隐藏,本意是讓使用者專注于編碼即可,但實際使用時通常會有自己配置的需求,此時執行npm run eject即可出現被隐藏配置檔案。

React-router 是官方推薦的路由管理工具,由于是單頁應用差別于原先的html界面間跳轉,跳轉實質是在元件間進行,是以需要有路由管理工具來統一化管理。這裡值得一提的是,React-router配合webpack可以實作代碼的按需加載。

一般來說,webpack打包後會在生成一個壓縮的js檔案,在單頁應用打開會整體加載這個檔案,由于該js檔案包含之前所有的js代碼,雖然進行了壓縮,一般仍至少有幾百kb,當應用稍微複雜點,打包後檔案會相應變大。而加載的時候,不管那些代碼有沒有執行到,都會下載下傳下來并進行加載,造成性能浪費,這一點在顯然在web端很重要,而在cordova中是将js代碼直接打包在本地,等于跳過了下載下傳步驟但仍然會有加載過程。通過在router中寫require.ensure代碼并在webpack中相應地修改配置即可将js分成多個檔案,在需要時加載對應的js檔案,實作按需加載。

Redux 是應用最廣泛的第三方狀态管理工具,其作用是當應用中多資料狀态互動時,可以更有友善且代碼結構清晰地統一管理狀态,下圖給出了形象的闡釋。由于在實際開發中一般是分人員/分功能子產品獨立開發,考慮引入redux的成本(redux本身略複雜),可以在沒有多資料互動的子產品不使用redux,而在類似涉及增删改查的表單以及即時通訊websocket等契合redux的子產品使用。

指尖前端重構(React)技術調研分析

為項目選取合适UI元件庫,一定程度上簡化UI樣式的開發并且考慮使用其提供的過渡動畫效果。這方面有比較多的選擇,Google Material Design 風格的Material-UI在github上最受歡迎,但其設計語言與我們目前APP截然不同,騰訊的weui和阿裡的antd-mobile 較為相近,其中antd-mobile與create-react-app腳手架配合使用時配置項比較繁雜,因為阿裡本意是用來配合自己的腳手架dva(封裝了react-router和redux),是以暫時選擇weui,後期開發有特定元件需求可結合其他ui庫使用。

至于頁面跳轉時的過渡動畫,有些UI庫給出了一些過渡樣式,比如touchstone。但該庫已不再維護,文檔不佳,且與新版本的react-router配合使用有不相容情況。後來浏覽官方文檔發現官方有動畫庫react-addons-css-transition-group,使用該庫結合css3的動畫三件套animation,transition,transform即可實作各種動畫效果包括基本的過渡效果,比如漸進平移等。

另外關于css,因為是單頁應用,是以如果不加處理,直接import css檔案的話最終打包生成一個css檔案會導緻樣式應用到全局,造成同類名樣式互相污染影響。解決這個問題有很多種方案。Facebook積極探索css in js方式,但直接寫内聯樣式代碼可讀性太差。目前解決方案中應用最廣泛的是css-modules,即在webpack配置中開啟module選項,使用styles對象來寫樣式。

解決的原理是将css類名在打包後編譯成哈希字元串,保持其唯一性。但當想要使用全局樣式時要再配置,稍顯繁雜,且它類名編寫的方式為對象的方式,需要整體修改,另外在使用它時,發現不支援-橫線的類命名方式,支援下劃線方式,推薦駝峰式,而我們之前html中的樣式類名大多是橫線命名,這意味着原html和css中的類名都要對應修改,考慮到樣式類名非常多,這一方式舍棄。

另外有基于css-modules使用高階元件的react-css-modules使用人數也比較多,允許橫線命名方式且全局本地樣式區分簡單,但有benchmark測試表明其會較大程度拖累性能,是以也舍棄。解決這個問題要最大程度相容原先css的寫法,即改動最小,因為之前的css類樣式數量龐大。

Webpack css-loader 有個屬性 :local 加上之後類會變成局部作用域,即webpack會對該類型的類進行自動哈希轉碼處理,但顯然類名一個個加:local 是有些呆闆的工作,于是想到可以利用scss的嵌套屬性将:local在一個css檔案中統一加到類名前。這裡涉及到在腳手架create-react-app 添加對scss的支援,在指令行執行安裝,并在package.json的scripts中添加watch-css指令,将原css檔案改為scss檔案,然後在最外層添加:local,執行watch-css指令,即可在scss檔案旁自動産生css檔案,且類名前自動添加:local 字首,這種方法實踐中發現并非所有類的樣式都與:local 相容良好,相應的可以使用檔案名代替:local,要做的就是保持檔案名的唯一性,這一點原工程下的檔案名已滿足。這樣原先檔案中引入css的方式,全局css引入的方式都不需要變化,做到最小代價。

scss 是 sass 3 引入新的文法,其文法完全相容 css3,并且繼承了 sass 的強大功能,sass和less是前端擴充css常用的方式,添加了嵌套,變量,繼承等文法,但需要編譯成css來最終使用(穩定性考慮)。

四、Reactjs 和cordova結合有哪些需要注意的

開發Reactjs使用官方提供的腳手架Create-react-app,最終通過npm run build生成一個單頁網頁應用,放入cordova的www目錄下即可。由于這兩部分開發時獨立,而原先開發是在含www目錄的cordova工程目錄下直接開發,這種不同會産生一些問題。比如cordova中某些插件安裝後export函數或者變量供引入使用,因為一開始是分離的,在create-react-app中并找不到這些變量,就造成在build的時候産生變量undefined的錯誤,盡管最終放到cordova工程中後可以找到變量并正常運作,但在第一步react開發時控制台報一堆error會妨礙調試,影響開發體驗。

在github上有一些react cordova 庫,但實質上它們都需要通過npm run build來打包,是以并沒有解決引入插件變量的問題,且會與create-react-app 有相斥的地方。是以要想辦法使插件提供的變量在React中不報錯,這裡在不影響ESLint 檢錯機制的情況下可以采取迂回的方式。Build時控制台報錯僅針對src檔案夾下的代碼,而在public檔案夾下還有個index.html這個檔案會最終被打包放到www目錄下,是以可以在這個檔案中deviceready時添加全局的插件變量(注意該類全局變量的唯一性,可以添加plugin字首或使用命名空間等方式保證),并将值傳給src目錄下的代碼中,這樣即可繞過控制台build以及調試時的報錯。

另外一個小技巧可以将react工程直接放在cordova工程目錄下,指定最終build生成的檔案放入www目錄下,省掉手動轉移檔案的過程。

還有需要注意的一點是由于React中預設配置的公共路徑是絕對路徑,當放在cordova中時需要使用file協定放本地,需要在webpack的production配置的public路徑前加".",或者在package.json 檔案增加一行"homepage": "../www"或"homepage": "."改為相對路徑,否則會出現找不到檔案的情況,這裡推薦最後一種方式。

五、React項目的目錄結構

首先IDE選取webstorm,功能強大,之前項目組在用可以沿用下來,但需要注意的一點是當目錄中包含了安裝的依賴node_modules時,由于該檔案夾下檔案數量非常多,webstorm在智能建立代碼關聯時會占用大量資源,在某些電腦上會偶爾會出現卡死現象,這一現象在我配置比較高(固态硬碟加8g運存)的電腦上同樣出現了,解決辦法是在file-setting-File types中配置ignore node_modules 檔案夾。

指尖前端重構(React)技術調研分析

上圖是create-react-app 項目的目錄,主要代碼放在src目錄下。Components中包含所有元件。React嚴格地執行元件技術,元件化不僅友善重用,同樣可以将一個頁面清晰地分割為幾個部分最後放入一個父元件展示,因為jsx技術将js和html放在了一起,分割後每個部分有自己的功能邏輯與頁面展示,這樣更加清晰易維護。事實上react提出了一切皆元件的思想,隻是有的元件render了部分界面,而有的沒有render。

上圖中components下有common檔案用來放項目成員自己寫的公用元件比如公共請求方法等,external放外部引入的元件,work_log裡放的是我寫的工作日志子產品的元件,各個功能子產品都各自建立一個檔案夾,命名規則統一使用下劃線方式,這也是之前使用的方式。具體功能子產品的劃分與層級關系可以參考之前的.

值得一提的,以前html的層級關系必須嚴格為兩層(涉及到跳轉路徑的邏輯),導緻最後出現沒有把一個功能子產品放到一個檔案夾裡的情況,比如上面的工作日志之前所包含的各個檔案直接和其它的一些功能子產品一起放到了setting檔案夾内。而現在隻要在React-router統一配置好路由,實質上是往某個元件跳轉,不存在跳轉路徑的限制。

Constants檔案夾下存放各種常量,比如各種接口路徑。Fonts存放字型圖示檔案,images存放圖檔,redux檔案夾下是redux的幾個組成部分,styles下放scss/css樣式檔案。Index.js是入口也是最頂層的父元件,router.js則維護了整個應用的路由關系。

上面就是本次調研的技術分析文檔,浏覽大量技術文檔,開源社群以及技術論壇并結合實踐摸索得出的選型思路和理由,可能依然會有一些點沒有添加進去,以後會結合新知識和實踐繼續完善。

作者:梁鑫

來源:宜信技術學院

繼續閱讀