攜程玩樂團隊前端多端開發實踐

一、前言

本文將介紹在具體業務實踐中,攜程玩樂團隊一套代碼多端複用的一些實踐與經驗,希望能給面對同樣問題的同學提供些思路和參考。

1.1 背景

在多端開發實踐之前,玩樂的前端開發存在如下一些問題:

1)技術棧架構繁雜且陳舊

到2019年2月,整個玩樂前端系統隨着不同需求的疊加積累以及其他原因,造成了不同業務線的基礎架構,技術棧不一致。當時的頁面技術棧包括:.net頁面、imvc頁面、nextjs頁面、jquey頁面等,這些不同技術棧的應用從寫法、結構、思想等方面都有不少出入。在公司全面推行React技術棧的背景下,諸如 JQuery、.net的前端技術架構顯得十分陳舊,各個技術棧之間形成了天然的技術壁壘,不利於代碼維護和人員培養。

2)統一產品需求,需要多端多渠道實現

改造前業務團隊是按照端和渠道來進行具體的需求劃分,如下圖所示:

這就意味着前端需要支持國內、海外包括 PC、H5、Hybrid、RN七個(海外版沒有Hybrid頁面)端的需求代碼實現,如果按照改造前的模式,將會有同學爲了這個需求更改6個倉庫的代碼。可以預見,如果這種模式不更正,前端開發將是在來回切換倉庫中度過的。

3)發佈困難,監控麻煩

正是由於技術架構不統一,所以改造前的應用從打包到發佈,其間的流程、打包技術存在很大差異,發佈變成了一件手動且不可預期的工作。改造前的頁面只是接入了一些公司日誌框架,對於一些業務性能指標、細顆粒度的指標並未記錄,這也導致了排查問題流程長,效率低下,開發人員只關注完成代碼並不知道頁面性能等問題。

1.2 舉措

針對前端系統存在的問題,我們進行了一些調研和不同框架之間的橫向比對。遺憾的是目前並沒有一套架構設計可以同時運行在多端,所以我們開始了對多端架構的持續開發與改造的過程,重點措施如下:

1)架構升級

對代碼結構和業務邏輯實現做合理劃分,在不同層級架構上做合理的事,並且對代碼做測試,引入新的日誌系統,接入新的打包發佈流程。

2)面向組件化的開發策略

儘可能多的將需求邏輯抽象成各個組件,再將這些組件拼接成頁面。基於這個角度,我們將組件劃分成基礎組件和業務組件兩個部分。

3)支持PC/H5/RN同時預覽

作爲多端開發的實踐,爲了確保開發效率,需要滿足一處修改多端同時可見。

二、架構簡介

爲了能讓RN和非RN的代碼同時運行,如果按照改造前的做法會出現如下一些問題:

1)由於是一套代碼,在發佈的時候會出現不斷改代碼配置然後再去發佈的問題;

2)代碼邏輯劃分不明確,會出現一類邏輯,到處都有的問題;

3)非RN打包中會出現RN的某塊代碼,從而造成打包代碼體積過大和其他不可預知的問題;

針對以上幾點,我們對前端架構做了升級,具體措施如下。

爲了確保一次修改多端發佈,我們按功能模塊將倉庫劃分爲四個層級,如下圖所示:

1)基礎、組件類庫

這個倉庫提供了頁面加載所需要的一些基礎服務,比如 React.Component的二次封裝、頁面信息生成、AJAX,fetch服務,定位服務等;以及一些與業務場景無關的組件,比如:多語言組件、彈框組件、價格組件等。

2)業務組件類庫和SSR倉庫

業務組件類庫爲業務開發需要關注的倉庫,所有的業務開發調試都是基於這個倉庫的。SSR倉庫提供幾部分功能,包括SEO,SSR會讀取業務組件倉管內不同頁面的生命週期,從而在不同的頁面內生成不同的SEO內容,以下爲頁面生命週期函數的邏輯,其中data爲服務端渲染的數據:

路由生成,這部分通過配置文件完成,具體配置文件內容如下:

  • IS_TRIP、IS_CTRIP、IS_ONLINE、IS_H5用於指定頁面屬性,爲false則渲染的時候不會生成該配置的頁面;
  • PATH:用於指定頁面路由;
  • CHILDREN:用於指定頁面的子頁面,用於SPA應用;
  • ALIA:非必傳,默認爲頁面文件名稱,用於獲取多語言服務;

配合SSR倉庫,業務組件類庫可以實現本地服務端渲染開發。

3)工程化倉庫

這個倉庫的提供的服務主要包括:

  • init 安裝所有依賴,可以支持多版本的RN依賴

  • watch 熱更新

  • dev 能同時運行crn、h5、online

  • ares 集成ares平臺打包靜態資源

  • precommit 提交前自動化review代碼規範

  • publish 自動化發佈nodejs資源

4)發佈倉庫

發佈所依賴的倉庫必定包含所有發佈所用到的資源,包括代碼和配置,之前的一貫做法是把前後端所涉及到的代碼和配置都統一放到一個倉庫內進行發佈,但是在多端統一的背景下並不適用。這種場景下代碼應當只有一套,變化的只有配置文件,結果就是開發倉庫只有一個,而發佈倉庫有多個,發佈倉庫被架空,裏面只發布配置,下圖爲一個發佈倉庫的目錄結構:

其中 app.config.js 爲應用配置信息,app.js爲入口文件,package.json爲發佈所依賴資源,其配置也很簡單,如下圖所示:

經過如上的倉庫拆分,我們能夠讓開發者只專注於業務組件的開發,其餘的基礎服務功能都能做到在一次開發,穩定使用的同時完成多端的同時開發和發佈。

三、具體措施

由於是面向組件化的開發策略,下面簡單介紹下組件多端開發的一些細節與實現:

3.1 服務和API封裝

這部分主要針對目前所要接入的第三方組件,包括多語言組件、頭尾組件、locale組件等。在定製API和上下文參數的時候,我們儘量向上擴展API。

比方說,我們的代碼內都不允許直接取中文,所有取文案的地方都是使用封裝的translate組件去拿對應文案。這樣的好處是,在使用、解釋層面ctrip和trip保持了統一,另一方面也爲以後ctrip可能存在文案走配置服務做了鋪墊,其他服務和組件API的封裝也遵循這個原則。

3.2 代碼職責劃分

我們遵循約定大於配置的原則,以單個頁面爲例,以下爲頁面的一些約定配置:

  • fetch:這一層負責頁面的網絡請求獲取,在做SSR渲染的時候,代碼會以這個文件入口獲取頁面所需要的數據,並以props的形式傳到頁面內;
  • view:這一層用來描述不同平臺的視圖展示,不通入口文件的UI結構基本一致,不包括任何的非UI展示邏輯;
  • fomat:重新組裝從restful下發的數據,經過這一層驗證和轉換後,後續邏輯都是即拿即用;
  • action:這一層是多端統一開發的關鍵,所有的頁面非UI展示邏輯都需要寫在這裏;
  • style:這一層配合view層決定了頁面具體的展示樣子,但和正常開發不同,這部分的模塊不需要手動引入,具體做法後面會介紹。

經過以上的約定劃分,我們的開發模式變成了開發人員拿到需求,先研究三端的view層代碼結構,確定出View的大致結構,然後先按H5的邏輯開發一套action和與之匹配的H5View。然後再在此基礎上做加法,去書寫RN的view,PC的view絕大多數情況下可以通過結構和樣式抹平差異,只需要在pc.scss去書寫差異化的css即可。

3.3 動態引入樣式

由於PC和H5頁面大多數情況下只需要通過樣式就可以做到多端實踐,所以在多數情況下並沒有index.pc.tsx和index.h5.tsx,只有一個公用的index.tsx,所以我們不能手動去引入平臺樣式。

我們做了這樣的處理,一是對單位做換算,.scss書寫的主單位還是px,由於某些原因我們在H5上的展示單位是rem,所以在打包的after-emit階段,通過插件把px換算成rem;二是在打包的buildModule階段,動態的將頁面依賴的css放進css依賴樹,從而實現動態打包效果。如下爲實現代碼:

3.4 運行時注入依賴

在做前後端同構的時候,以fetch模塊爲例,假設只是簡單的判斷前端用前端的ajax模塊,服務端用服務端的request模塊,邏輯看起來沒問題。但是事實上如果在打包邏輯上沒有做比較複雜的改進,那麼是不可能打包成功的。

所以通常的做法,是在邏輯中先聲明一個爲空的變量,在運行時初始化這個變量,那麼在代碼執行到該處邏輯變的有意義,而打包由於是靜態檢測所以並不會把任何不需要的代碼打進包內。這裏在處理RN模塊和正常的H5模塊的時候也採用類似的技術:

1)我們會在有RN模塊的場景下聲明一個rn-polyfill.ts,大致內容如下:

2)在index.rn.ts中對變量賦值:

3)在我們的初始化RN頁面(比如index.ios.js)中引入 index.rn.ts。

這樣的話,我們就實現了模塊打包的分離。

四、結語

由於篇幅原因,其他模塊(測試、日誌監控等)的介紹這裏就不進行了。

先介紹下改進後的效果,組內成員除開業務邏輯整理,可以做到無縫替換開發;和之前開發模式對比,同一個需求多端完成時間,節省了近四成。目前框架功能依舊在不斷地迭代和更新,近期希望能消除view和style層需要同時書寫的情況,從而讓開發迭代更加效率和速度。

作者介紹

Neo,攜程前端開發工程師,負責玩樂前端架構相關開發工作。

本文轉載自公衆號攜程技術(ID:ctriptech)。

原文鏈接

https://mp.weixin.qq.com/s?__biz=MjM5MDI3MjA5MQ==&mid=2697269626&idx=1&sn=814a23938b1480dda706e061c5dbf222&chksm=8376ee4eb4016758f50414a5c4d344ef4aee5ef5373706b63c1edb6996e191b59433e7ff2fec&scene=27#wechat_redirect

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章