詳解|天貓搜索前端技術歷代記

導讀:做者從 17 年雙十一前開始接手天貓搜索前端,開發第一個需求—— H5 湊單頁,到今天已經將近兩年了。在這兩年裏,天貓搜索的前端體系發生了比較大的變化。今天分享一篇階段性的總結文章,記錄天貓搜索前端技術的過去、如今,以及本身做爲業務目前的惟一前端對將來的思考。

大致劃分css

首先基於前端技術的演進,大致上能夠將天貓搜索前端的發展歷程和將來趨勢總結成幾個時代:前端

  • PC 時代
  • H5 時代
  • MV* 時代
  • Weex 時代
  • 搭建時代
  • 深度搭建時代
  • 智能時代

之因此這麼劃分,主要是基於天貓搜索的前端技術方向以及天貓乃至淘系前端技術體系發生的較大變化。而在這其中能夠再提煉時代的關鍵詞:react

  • 封閉:PC 時代、H5 時代、MV* 時代
  • 開放:Weex 時代、搭建時代、深度搭建時代
  • 智能:智能時代

下面就來介紹各個時代天貓前端的技術狀態和一些思考。webpack

一、PC時代

PC 時代能夠說是天貓搜索前端的上古時代,那仍是手機流量很是貴的 3g/2g 時代。所以大多仍是簡單的 WAP 頁面,大多數人都仍是習慣用 PC 進行購物。ios

▐ 技術方案web

模塊化後端

PC 時代的前端技術方案採用的是 KISSY + MUI 3 ,MUI 3 就是那套 KISSY 的模塊規範 KMD 。頁面上還有一些很是老舊的 YUI 依賴。在那個 jQuery 王霸天下的時代,基本上天貓的 PC 頁面都是採用集團內部根據 YUI 自研的大而全的 KISSY 框架。KISSY框架包含了前端所須要的幾乎全部基礎功能:模塊加載器、 DOM 操做、事件處理、異步請求等等。瀏覽器

頁面渲染緩存

PC 天貓搜索採用了同步渲染的方式,頁面的主要內容經過 VM 模板渲染輸出到前端,所以前端須要維護大量的 Velocity 模板代碼以保證 HTML 中的內容和本身 JS 代碼可以配合得當。需求修改一旦涉及到 HTML ,就須要改造 Velocity 模板從而陷入 aone 發佈的同步模板和部署煉獄之中。性能優化

模塊管理

而 PC 時代的天貓搜索前端頁面的模塊管理方式十分粗暴,基於業務邏輯劃分的大量 KISSY 模塊,他們共同操做一個統一的頁面 DOM ,交叉修改時有發生。模塊間的通訊也是直接調用模塊實例方法來實現,模塊耦合很是嚴重。

▐ 小結

由此能夠看到那個時代最主要的問題有以下幾個:

  • 大而全的框架使得頁面笨重、依賴繁雜
  • 前端花費大量成本去維護不熟悉的 Velocity 代碼
  • 基於應用環境,常常性須要同步模板或部署,應用不穩定時甚至沒法調試
  • 頁面內模塊化粗暴,模塊耦合嚴重
  • 重 DOM 操做,DOM 管理混亂

二、H5 時代

隨着智能手機的普及,4g 技術的發展使得流量費用的大幅降低,無線端需求不斷增多,流量不斷增大,天貓前端也將方向定爲 mobile first 。顯然 PC 搜索這一套技術方案沒法知足 H5 搜索需求,所以 H5 搜索採用了全新的技術方案。

▐ 技術方案

模塊化

H5 搜索採用 Zepto + MUI 4 做爲模塊化方案,MUI 4 相對 MUI 3 主要變化是將 KMD 規範修改爲了業內較爲通用的 AMD 規範。同時引入了前端模板來實現 DOM 的更新,首先 Zepto 要比大而全的 KISSY 輕量許多,同時前端模板的引入使得模塊自我管理了 DOM ,有效的下降了模塊之間 DOM 操做交叉引起的混亂。

頁面渲染

H5 搜索的頁面渲染基於應用控制,但僅僅將框架、篩選等一些少許 DOM 同步渲染,大多數 DOM 如商品列表都是採用異步渲染前端模板的方式實現。所以同步模板中的內容量相對較小,維護成本大幅度下降。同時引入了先後端分離的 wormhole app ,前端再也不須要維護不熟悉的 VM 模板,而是維護和異步模板語法相同的 xtpl 模板,進一步下降了模板維護的成本。

模塊管理

與 PC 連翻頁都是頁面跳轉的方式不一樣,如篩選、翻頁等行爲的渲染須要前端異步處理,模塊通訊的需求也相對複雜。H5 搜索採用了 MDV 框架——經過將模塊封裝成一個個模型,再由 MDV 創建的模型之間的訂閱機制進行模塊的實例管理,以此來實現模塊通訊。

▐ 小結

H5 搜索採用的技術解決了幾個 PC 搜索時代的問題:

  • 減少依賴,知足了H5的性能要求
  • 基於wormhole app的先後端分離開發,下降了模板維護成本
  • 引入前端模板,下降了DOM交叉管理的混亂
  • 引入MDV進一步使得模塊解耦,規範了模塊通訊

但隨着業務的發展,依然發現有一些問題:

  • 雖然引入了前端模板,但全部更新和狀態同步依然是手動的,依舊會頻繁地 DOM 操做
  • 模塊劃分仍是基於邏輯劃分,而非基於 DOM ,所以當一個邏輯模塊須要操做多個 DOM 時,依然會引起交叉
  • 雖然模塊對外是個黑盒,但模塊內部狀態常常由於交互邏輯和業務邏輯繁瑣致使混亂,常常出現更新了狀態沒更新 DOM 的狀況
  • 依賴應用環境,須要常常性同步模板和部署,畢竟 wormhole app 也是應用

三、MV*時代

在 all in 無線的大環境下,因爲搜索結構較爲固定、無線端開發資源較爲充裕等等各類緣由,天貓搜索業務在端內徹底被 Native 承接,而 H5 更加註重端外和站外。這也致使了 H5 搜索的業務能力和 Native 脫節,僅保留核心篩選功能以及喚端功能。所以 H5 搜索很長一段時間幾乎沒有前端資源投入,而在 2017 年 8 月左右因爲組織架構調整,我手上的天貓商品業務交接後,我開始逐步接手天貓搜索前端業務。而我要作的第一個需求,就是一個包含 H5 搜索 80% 功能的 H5 搜索湊單頁。

▐ 技術方案

模塊化

我和團隊同窗採用 Preact + MUI 5 方案來實現,MUI 5 其實就是 MUI 4 的升級,採用 CommonJS 的寫法來編寫模塊,再通過構建工具編譯封裝生成 AMD 模塊。其實當時會場已經大規模採用 Vue Weex 了,那咱們爲何要採用 Preact 呢,主要是基於以下幾點考量:

  • 團隊內對於 React 技術棧有至關程度的瞭解
  • Rax 的發展和普及以及 Weex 團隊的一些調整,讓咱們認爲 Rax 是將來 Weex 的主要 DSL
  • Preact 相對於其餘框架更加輕量,而搜索的頁面雖然有必定交互,但比較簡單,恰好能知足需求
  • H5 是將來大的趨勢,當時兄弟團隊在天貓超市的極致 H5 體驗和沉澱給了咱們充足的信心

所以在這個階段,咱們使用 Preact 作了不少的搜索周邊的功能頁面,如上面提到的 H5 湊單、還有貓搜的領券彈層、湊單領券頁面、搜索分類頁面等等。

頁面渲染

因爲 Preact 的異步渲染特性,頁面渲染咱們直接拋棄了應用,而是採用斑馬源碼頁面的方式。這樣的好處是,前端再也不須要和 aone 頻繁的打交道,服務端只須要封裝一個 mtop 接口給前端,前端在斑立刻建立基礎 HTML 引入資源並調用接口獲取數據渲染便可,前端本身徹底掌控了調試、開發節奏。因爲對於應用的依賴僅限於一個 mtop 接口,所以前端能夠提早定好數據規範,在服務端開發接口的同時基於本地調試工具進行 mock ,大大下降了聯調成本。

模塊管理

React 生態有很是多的模塊管理方案,咱們調研過的 Flux、Redux、Reflux 等等均可以知足咱們的需求。但通過仔細的思考咱們選擇直接擼,不使用任何框架來管理模塊通訊。如此考量的緣由主要遵循以下理念:

  • 首先咱們須要規劃頁面的模塊結構和通訊結構
  • 若通訊結構與模塊結構有較大的出入,且通訊結構並不是扁平,那麼咱們就須要引入模塊通訊框架來實現通訊結構的扁平化
  • 若通訊結構與模塊結構出入不大,且通訊結構自己扁平,那麼咱們就沒有必要引入通訊框架
  • 保持模塊結構清晰、分離,面向將來,若將來業務發展逐漸繁瑣,能夠再引入框架來處理模塊通訊

▐ 小結

引入 MV* 框架後,咱們的技術方案又獲得了一些提高:

  • 因爲引入 MV* 框架,模塊的劃分再也不基於邏輯而是基於 DOM,DOM 的操做再也不須要手動處理, DOM 交叉操做被完全杜絕;
  • 使用斑馬源碼頁面,再也不依賴應用環境,更方便的數據模擬和調試。再也不須要維護模板;
  • 模塊內部狀態基於 MV* 管理,狀態再也不混亂,保證了 DOM 和模塊狀態的一致性;

這裏仍是有一些問題:

  • H5 老是面對性能的挑戰
  • 依然是源碼開發,不夠靈活,也沒法共建
  • 每來一個需求,就須要頁面總體修改和發佈,有相似行業定製,只能從新開發一個

借鑑天貓超市極致 H5 經驗,搜索在分類頁作了很是多性能優化嘗試,好比:

一、代碼優化

  • 列表拆分 cell 進行懶加載
  • 接入 crossimage 優化圖片加載的 cdn 後綴
  • 自建 solution ,去除通用 solution 中各類無用依賴
  • 升級最新的 loader 來提高計算性能

二、DNS優化

  • dns-prefetch,提早處理dns
  • 收斂圖片和資源域名

三、接口優化

  • 使用dlp進行mtop接口緩存

四、埋點優化

  • 令箭埋點延遲到 pageload 後發佈
  • 採用非覆蓋式的 aplus 腳本,利用瀏覽器緩存
  • 採用 post 發送,觸發 sendBeacon

五、加載優化

  • 增長 service worker 層緩存 js、css 和圖片
  • 使用 zcache 緩存頁面模板、 js 和 css

六、體感優化

  • 使用 ranger 自動添加 URL 隱藏導航欄參數,防止頁面加載後手動隱藏出現的抖動

四、Weex 時代

17 年雙十一以後,搜索一成不變的模式也受到挑戰,在這個擁有大量流量和強用戶心智的場景下,搜索可以玩出更多場景化、行業化、品牌化的玩法。所以產品上須要更多快速試錯的機會,也致使對於動態化的訴求則日益增長。而因爲一些組織架構調整,天貓搜索的客戶端縮減到 2 人—— 1 個 ios 和 1 個安卓。客戶端需求開發由於須要發版而迭代緩慢。所以催生了 Native 內嵌 Weex 坑位的技術方案和 Weex 模板下發的 Oreo 平臺。

▐ 技術方案

模塊化

其實在我進入到搜索以前,Weex 坑位方案和 Oreo 就已經在小範圍使用了,有一部分客戶端同窗寫的 Weex 1.0 的 Vue 模塊,另外還有一些 Weapp 模塊。這些模塊因爲人員調整和離職已經很難找到倉庫源碼了。另外這些模塊也是僅面向 Weex 的,對於 H5 來講是徹底沒法使用的。所以在我進入搜索以後,提出了Prax的解決方案,本質上就是使用 Rax 0.x(當時仍是0.4) + Preact 經過編譯轉換供Weex和 Web 同時使用。之因此要用Preact,主要是考慮到咱們有端外 H5 場景,可是 Rax 當時 H5 性能是真的堪憂,並且當時的Weex團隊方向對H5性能優化投入並很少。另外從上面 MV* 時代能夠看出咱們在 Preact + MUI5 的技術方案上也有較多的沉澱。最終咱們肯定了採用編寫 Preact 代碼,經過自動化工具轉換成 Rax 代碼的方式來實現一份源碼同時複用在 Weex 和 Web 的技術方案。前端的開發流程就變成了以下:

  • 編寫包含基礎可複用純 UI 代碼的 Prax 模塊
  • 對於 Native 內嵌 Weex 坑位,編寫一個 Rax 模塊, Rax 模塊引用 Prax 模塊的 Rax 部分,並增長諸如埋點、容器聯動等功能,並經過專門的模板發佈系統發佈上線以供坑位使用
  • 對於 Prax 頁面,編寫一個斑馬模塊或頁面,引用 Prax 模塊。經過斑馬平臺發佈上線,在端內使用 Prax 頁面的 Weex 版本,在端外引用 Prax 頁面的 H5 版本

頁面渲染

Prax 頁面採用斑馬來處理頁面渲染。因爲源碼頁面都是採用打包的方式,所以腳手架中分別有 Web 和 Rax 兩個打包 webpack 配置,構建時候分別運行生成 Weex Bundle 和 Web Bundle 。因爲 Web 端本質上就是以前 Preact 的方式,所以渲染沿用了過去 Preact 的頁面框架。而Rax則是開發了一個全新的頁面框架。斑馬渲染 Weex 頁面本質上是經過xtpl控制 Weex Bundle 代碼生成,因此源碼頁面編譯出來的 Weex bundle 只須要在外經過 xtpl 增長一層 Weex 的頭尾就能夠了。

對於 Native 內嵌坑位,則是採用模板下發的方式。前端會編譯生成一個自身可運行的 Weex Bundle ,包含頭尾等完整信息,而後經過發佈推送到搜索應用的機器上。當客戶端的搜索請求到達服務端,服務端基於業務邏輯肯定須要使用哪些模塊,將模塊相關的信息告訴客戶端,這些信息包括模塊名稱、模塊位置、模塊數據。客戶端渲染 Native 頁面時根據模塊位置建立對應容器,並根據模板名稱請求 Weex 代碼,最後將代碼渲染到 Weex 容器中,並傳入模塊數據,實現模塊最終渲染。而在 Rax 代碼中,咱們能夠經過 window.__weex_data__ 拿到客戶端塞給容器的數據。固然這些適配均可以在構建層面處理,通常狀況下開發者只須要關注純粹的 UI 模塊編寫便可。

模塊管理

Prax 頁面的模塊管理和 Preact 開發時期基本同樣。可是對於 Native 內嵌 Weex 坑位,模塊管理方案就徹底不一樣了。看起來 Native 內嵌 Weex 坑位只展現一個Weex模塊,但其實是一個只有單一模塊渲染的完整 Weex 頁面。所以 Weex 模塊之間是沒法通訊的,它們甚至都不在一個 Weex 容器內。正由於如此 Native 內嵌 Weex 大多作一些純展現的需求,對於複雜聯動需求依然是交給客戶端完成。另外客戶端提供了一些通用能力,封裝在 Weex 模塊中,如:

  • 獲取搜索當前篩選條件
  • 合併篩選條件並從新請求
  • 清空篩選條件並從新請求
  • Query 詞替換
  • 一次篩選內 mtop 緩存機制
  • ...

▐ 小結

通過了 Weex 時代,咱們的技術又獲得了提高:

  • 實現了一套代碼同時複用在 Weex 和 H5
  • 經過引入 Rax ,咱們解決了端內的性能問題
  • 對於端外場景,咱們也保證了 H5 性能以及優化的抓手
  • 靈活的 Weex 發佈機制突破了發版限制,知足了產品的動態化訴求
  • 對於搜索坑位,咱們也沉澱出了一套行業前端能夠參與共建的機制

但這裏仍是有幾個問題沒有解決:

  • 源碼頁面開發的問題依舊,不夠靈活,也沒法共建,也很差複製多個
  • 搜索坑位內模塊展示邏輯是服務端硬代碼控制,對於行業規模化和動態數據源接入都須要從新編碼
  • 當多個模塊同時做用於同一場景時,模塊的展現邏輯就會交叉,引入各類各樣的問題

五、搭建時代

至此咱們能夠發現,如今搜索前端核心解決的問題逐漸變成了共建和規模化了,再也不是以前單純前端技術問題了。既然要解決共建和規模化,咱們能夠看看規模化成功的一個典型例子:會場。過去會場也是一個個頁面前端人肉開發,到後來有了斑馬就能夠由運營模塊化搭建了,前端只須要開發一些基礎模塊就能夠知足全部行業的訴求,多麼的美好!那麼搜索是否是也能搭建呢?

答案是:「是的」,但畢竟場景不一樣,咱們不能和會場同樣樓層 duangduang 地堆砌,爲何呢?

首先在場景的層面有比較大的不一樣。在用戶進入這個會場時,已經決定了當前的場景了,一個會場頁面就是一個場景,所以在這個會場頁面下,只須要圈出這個場景的模塊就能夠了。而對於搜索,全部的場景都須要在搜索這一個頁面展現,而在搜索如何定義一個場景呢?

  • Query 詞:用戶搜了什麼詞,是品類詞、仍是品牌詞、仍是寬泛詞、仍是一個具體的型號詞
  • 類目:用戶搜的詞所屬的類目是什麼?哪一個一級類目?哪一個葉子類目?或者說是橫跨不少類目?
  • 人羣:用戶本身是哪一個人羣,潮流酷女?仍是居家好男人?
  • 時間:用戶在什麼時間來的?聖誕節?新年?生日?
  • LBS:用戶在什麼地方來的?附近是否是有提供服務的門店?
  • ...

這麼多維度,一個或多個交織在一塊兒才定義了一個場景,而在這個場景下會展現一個或多個模塊。

以 Query 舉例:

  • 用戶搜索品牌詞(如華爲):展現品牌搭建的 Minisite
  • 用戶搜索特定類目詞(如香水):展現行業模塊
  • 用戶搜索禮物(寬泛詞):展現禮物場景導購卡片
  • ....

固然,會場模塊裏面的貨品徹底能夠多樣化,另外如今會場基於袋鼠也有千人千面模塊的能力了,這裏是拿以前的會場作例子

基於這樣的思考,搜索啓動了一個長頸鹿項目,以以前搜索域就有的一個產品——品牌 Minisite 做爲切入點,爲品牌商提供了一個全新的品牌運營陣地

如上圖,從左往右分別是三個版本的 minisite 。這裏能夠看到, Minisite 做爲品牌在搜索的一個搭建陣地,一直採用的是提供模塊讓品牌商填入數據的玩法。品牌商自定義程度很低、維護慾望很低,所以導購效率一直不高。而在長頸鹿項目中,搜索在商品列表層之下又新開了一個層,在這個層裏展現一個品牌商家搭建的頁面,在這個頁面中品牌商家能夠充分的自定義。而對於一個跨品類經營的大品牌,咱們也開放了品牌詞+主營類目詞的組合,方便其對每一個主營類目去搭建本身的頁面。

而在品牌詞下取得成功後,咱們將能力擴展到了行業側,在搜索中臺——美高上建設了心智造產品。讓行業也能夠基於一樣的方式去經營品類詞,搭建行業本身的頁面。

心智造和 Minisite 分別是針對品類詞和品牌詞,相互不會交叉。而對於一些橫跨多品類的平臺級需求,好比一些頻道相關的需求和拉新相關的需求,是很是容易與其餘場景交叉的。爲了解決這個問題,咱們在美高上沉澱了一套模塊定投方案——無界,經過模塊級別的投放,讓場景之間的交叉變成可能,只須要簡單定義模塊展現的規則,就能讓不一樣場景的模塊展現在同一個頁面上。

▐ 技術方案

模塊化

首先是心智造和 Minisite ,它們的核心技術方案是類似的——都是採用千葉(一個給商家用的頁面搭建平臺)做爲模塊搭建平臺,並在千葉的搭建能力之上,包裝了一層頁面投放策略的管理。其實到這裏,模塊化方案和會場並沒有二致,只是模塊的實現採用了 Prax 來兼容 Weex 和 H5 :

一、編碼階段

  • 每一個模塊都會定義本身投放的數據結構
  • 模塊內不包含頁面通用依賴(如 Rax 基礎組件、 mtop 等)

二、渲染階段

  • 有一個 Solution 控制頁面模板的渲染,對於Weex則是負責包裹 Weex 頭尾
  • Solution 將模塊相關數據規整,Web模塊代碼能夠異步獲取, Weex 通常同步輸出到 Bundle 中,而模塊所用的數據都會放在頁面上提供一個簡易方法獲取
  • Soluiton 引入 PI(頁面初始化腳本), PI 將相關模塊數據取出根據模塊信息獲取模塊代碼進行渲染,並從頁面上獲取數據交給模塊

而到了無界,這些就徹底不 work 了。畢竟無界是走的模塊級定投,容器只有一個,所以投放場景極可能和心智造、 Minisite 場景交叉:

  • 沒有模塊也沒有心智造和 Minisite 頁面,那麼咱們就須要建立一個只展現無界模塊的頁面
  • 已經有心智造或 Minisite 頁面了,咱們須要將當前模塊插入到頁面中

而咱們採用了以下技術方案將無界的定投模塊插入到頁面中:

  • 用戶發起搜索,搜索請求到達服務端
  • 服務端請求返回時,若命中心智造和 minisite 場景,則返回對應場景投放的千葉頁面 URL
  • 服務端請求返回時,若未命中心智造和 minisite 場景,且命中有無界定投的模塊,則返回一個空頁面 URL
  • 服務端請求返回時,若命中有無界定投的模塊,則返回無界定投模塊信息,包括模塊名稱、模塊版本、模塊數據、展現規則
  • 客戶端建立長頸鹿 Weex 容器,渲染心智造、 minisite 頁面,或者空頁面,而後將無界定投模塊數據傳入 Weex 容器
  • 頁面渲染觸發 PI 執行,PI 獲取無界定投模塊,拉取定投模塊的代碼,建立實例後基於展現規則插入到頁面中

經過這樣的方式,最終渲染出當前場景下全部的模塊內容。另外在無界後臺咱們有一套場景干預規則,解決場景交叉時進行一些手動干預。與此同時咱們還提供了一套動態數據源機制,方便三方 HSF、TPP 數據能直接綁定到模塊上,實現模塊和數據解耦。

頁面渲染

頁面渲染如上述所示,依舊是經過斑馬。但與以前不一樣的是:

因爲是模塊化搭建,頁面經過 PI 統一管控,頁面渲染依賴 PI 行爲控制

對於長頸鹿容器,一樣是 Native 建立 Weex 容器渲染,但與以前渲染一個僅包含一個模塊的 Weex 頁面顯然是不一樣的,長頸鹿容器內渲染的也是一個真正的模塊化搭建的頁面

對於無界定投的模塊,提供了插入機制,解決了場景交叉時的展現問題

模塊管理

對於頁面內的通訊,因爲頁面經過 PI 統一管理,也就意味着模塊的各類能力都須要依賴 PI 來進行實現。因爲這樣的樓層搭建通常通訊結構都是扁平的,因此基本上經過模塊冒泡給 PI , PI 下發給對應模塊便可。不過通常不建議模塊之間進行通訊。

對於頁面和容器通訊,咱們是在 PI 中提供了一些封裝的能力,另外也能夠本身調用容器提供的方法,與 Native 內嵌坑位的 weex-module 方案別無二致。

▐ 小結

因爲長頸鹿內的技術方案已經脫離傳統意義上的前端,更多設計客戶端和服務端,是整個產品架構的設計,這裏很難講清楚,放一張圖可能清晰一點:

這裏前端技術又有了提高:

  • 實現了可視化搭建,爲商家&行業提供了運營陣地
  • 爲將來品牌&行業規模化提供了基礎
  • 提供了更好的行業共建機制
  • 動態數據源+無界模塊定投能力更加靈活多變

但這裏咱們仍是有幾個問題還沒有解決:

  • 咱們和會場愈來愈像了,可是咱們和會場模塊並不互通(會場終於也用 Rax 了,可是他們用的是 Rax 1.0,咱們仍是 Rax 0.6)
  • 搭建的粒度太粗,基於樓層的搭建不夠靈活沒法知足行業差別化訴求(想象一下搜索列表做爲一個模塊時,只是商品樣式改下就要從新開發一個搜索列表)

六、深度搭建時代

搜索最擅長的顯然就是搜索結果頁那種商品瀑布流,將用戶最想要、最有可能購買的商品推薦給他們。而這個能力也能夠複用在諸如首頁、頻道、店鋪、專輯等等地方。而當咱們要在不少不一樣的地方去搭建這樣一個列表頁時,在上面所說的樓層搭建中,咱們通常會怎麼作呢?

  • 首先,新建一個 XXX 搜索列表模塊
  • 找一個無盡列表組件
  • 開發這個業務須要展現的商品坑位
  • 將無盡列表組件裏的 loadmore 中去請求 mtop 獲取下一頁數據
  • 將模塊發佈供搭建使用
  • 當有新的需求,就新增一個標記來判斷,基於標記換一個數據和商品坑位展現

若是這麼處理,若行業大面積規模化,會出現以下幾個問題:

  • 不一樣行業對於商品展現的要求不盡相同, 好比家電行業都會展現一些比較關鍵的產品屬性,而家裝行業則要更突出一些上門安裝的服務,這也就致使商品坑位的展現不一樣,同時也意味着大量的開發成本
  • 因爲在一個倉庫內開發,共建會更加困難,全部需求都會更容易壓到本身頭上
  • 因爲對接不一樣數據源,當業務邏輯出現交叉,前端代碼裏的各類判斷也會指數級增長

這些顯然都是咱們不肯意看到的,咱們將組件的不一樣場景徹底剝離,能夠發現一些規律:

  • 無盡列表既然能抽出一個組件,那麼它確定是能夠複用的
  • 商品的展現和數據源的接入其實很是適合共建,讓行業的前端對接行業本身的數據=專業的人作專業的事

進一步提煉:

  • 交互可複用
  • UI 根據場景自定義
  • 數據根據場景自定義

因此咱們有沒有可能在這個理念上更深一步進行搭建呢?

模塊化

答案顯然是有的,深度搭建的概念其實就是用來解決這種問題。將頁面上的模塊基於功能進行了從新定義:

  • 數據模塊:自身沒有任何 DOM 相關代碼,只負責處理數據。而且監聽一些事件,這些事件觸發時會加載新的數據並將其交給接收其數據的下游模塊,觸發刷新
  • 容器模塊:自身實際上是一個容器,負責接收數據,並將數據下發給展現模塊去展現。但它自身不處理數據,而是經過觸發數據模塊定義的事件接口,告訴數據模塊須要作什麼。
  • 展現模塊:UI 展現模塊不處理任何邏輯,惟一作的就是拿到交互容器模塊給他的數據作展現。它內部甚至不處理任何事件,全都是以冒泡的方式到交互容器模塊進行處理。

經過這樣子的劃分,容器模塊控制了交互、展現模塊控制了 UI 、數據模塊控制了業務邏輯,好比一個包含篩選、商品流的列表更具體用 React hooks 來講就是:

  • 數據模塊本質上就是一個 reducer,對外暴露一個 [state, dispatch], state 包含篩選信息、商品數據,交給容器模塊渲染;而 dispatch 則定義了 loadmore 、 changenav 等方法,供容器模塊調用
  • 容器模塊將導航和商品坑位定義爲純展現區域,將篩選信息、商品數據傳給關聯的展現模塊進行渲染,並傳遞給他們一些如點擊事件的回調方法,當篩選發生點擊時經過 dispatch 觸發數據模塊的 changenav ,而頁面下拉到底時經過 dispatch 觸發數據模塊的 loadmore
  • 展現模塊就是純粹的無狀態 UI 組件,不一樣的組件用來展現不一樣的區域

合理的場景劃分相當重要,不一樣業務場景應該是數據模塊+容器模塊+展現模塊的組合,大多數狀況下容器模塊和展現模塊能夠複用,但數據模塊都是須要從新開發的。儘量讓數據模塊來適配容器模塊和展現模塊,不改變交互就不改變容器模塊,不改變UI就不改變展現模塊。

在這裏模塊的編寫切換到了 Rax 1.0,與會場的開發方式一致以實現複用。Rax 1.0 針對 Web 作了不少優化,打出來的 bundle 也更加輕量,性能也好了不少,已成爲天貓前端業務開發主要方式,所以再也不須要使用 Prax 了。

頁面渲染

這裏和傳統搭建有個很重要的不一樣,模塊之間出現了關聯關係。好比以下關聯:

  • 數據模塊須要和容器模塊&展現模塊相關聯,須要將 state 和 dispatch 交給對應模塊
  • 展現模塊與容器模塊管理,容器模塊定義了區域,不一樣區域使用不一樣的展現模塊
  • 容器模塊甚至能和容器模塊作關聯,實現多層嵌套展現,這種狀況通常用於純展現,不涉及交互(好比搜索列表篩選欄和商品瀑布流中間的空白區域)

那麼咱們就須要一個全局方式來處理這些關聯。首先須要在搭建模塊的時候去指明模塊之間的關聯關係,好比我本身是定義了三個字端:

  • key :模塊的惟一標識,給容器和數據模塊使用
  • data :若是是容器或展現模塊,在其中填入所使用數據模塊的 key
  • container :若是模塊在另一個容器以內,則在其中填入所在容器模塊的 key

data 和 container 都是二段結構的,好比 data 的 a:b 表明使用 key 爲 a 的數據模塊的 b 字端內的數據,而 container 的 a:b 則表明使用key爲a的容器模塊,並將本身做爲其 b 區域的展現模塊使用。

這幾個字端都會在腳手架裏,初始化時生成到 schema.$attr 中。而真正負責識別這些字端並將模塊串起來的天然是頁面初始化腳本—— PI ,PI 幹了以下事情:

  • 掃描全部數據模塊,並將其實例化,存放在一塊兒,並從渲染模塊中將其剔除
  • 將剩餘的渲染模塊基於 container 組織成一個樹形結構,並對每一個節點基於 data 關聯數據模塊,並將最上層進行渲染
  • 將子模塊相關數據傳遞給容器模塊,並提供一個默認渲染方法。容器模塊能夠本身決定如何處理這些子模塊相關數據,能夠修改、合併、覆蓋,修改完後使用渲染方法渲染便可。若其中還有還有下一級子模塊,重複進行以下操做

模塊管理

這裏模塊的通訊有兩種,一種是基於公用數據模塊的通訊,一種是基於 PI 的通訊。

一個頁面上能夠有多個數據模塊,而每一個數據模塊均可以對接到多個容器/展現模塊(這也是爲何 data 是二段結構的緣由)。所以當多個模塊須要通訊的時候,能夠經過dispatch觸發數據模塊行爲,數據模塊刷新數據影響另一個模塊。

基於PI的通訊通常都是針對一些特殊場景,好比一個很經典的例子——篩選列表篩選欄變形吸頂:當頁面有不少模塊,篩選列表並非全屏大小而是跟着整個頁面一塊兒滾動,當篩選欄滾出視野外,它須要變成一個相對簡單的結構吸頂。在這種場景下,因爲吸頂層自己是一個絕對定位的層,而頁面文檔流也是一個層,兩個層之間不基於 DOM 操做的話,最合理的方式就是基於一個數據模塊進行狀態共享。如吸頂組件定義了吸頂時的樣式和正常的樣式,而且暴露一個建立數據模塊的方法, PI 在渲染吸頂組件時會單獨爲其建立一個數據模塊來共享篩選欄狀態。

▐ 小結

爲何要搞的這麼複雜?其實就是但願能將 UI 和交互作的更加純粹,當 UI 和交互都是針對單一場景、足夠簡單的時候,咱們就能引入一些產品來進行提效,好比:

  • 使用描述式的方式來零開發定義交互,生成容器模塊,如 domagic
  • 使用描述式的方式來零開發定義 UI ,生成展現模塊,如 imgcook /魔切

經過這這樣的方式,最終頁面上大多數內容都變得能夠複用,規模化的成本也就大大下降了。

七、智能時代

因爲搜索還在深度搭建時代探索,如下是我基於團隊方向 YY 的,但我相信這個時代很快就會到來

但上述的各類方式終究仍是人肉的,須要人力投入的。既然工具能讓咱們以配置的方式解決交互和 UI ,那麼有沒有可能連配置都不須要,機器自動幫咱們生成一個數據模塊或者交互呢?

這就是咱們團隊正在作的,目前團隊的同窗正在嘗試基於機器學習訓練模型實現智能化UI。只須要給出一些關鍵信息(好比要展現商品的哪些字端),就會自動化的生成對應的展現模塊或交互模塊。這些模塊使用到深度搭建之中,前端就只須要經過數據模塊定義展現的內容來源就能完成整個頁面的搭建。實現UI零成本。

而咱們進一步擴展去思考,把大象裝冰箱分爲三步,那麼把搜索智能化應該也只須要三步:

  • 第一步,咱們告訴機器要展現什麼內容,它用最高效的方式展現給用戶
  • 第二部,咱們告訴機器要展現哪一類的內容,它找出這一類內容最高效的方式展現給用戶
  • 第三部,咱們告訴機器咱們的場景,它找出符合該場景的內容展示給用戶

具體一點多是:

  • 第一步,咱們有了商品,讓模型去訓練出最好的商品展現方式
  • 第二步,咱們定義了說這裏要展現一個權益模塊,那麼模型會給出最合適的展現內容,好比說展現一張店鋪券,是展現店鋪券的同時展現幾個爆款商品誘導用戶去下單,仍是站在一個商品的維度將店鋪券結合品類券、津貼一塊兒給出一個驚人的折扣價誘導用戶下單,抑或是找出當前用戶指望購買的商品總價最接近的店鋪券展現並誘導其湊單等等
  • 第三步,咱們定義了一個場景,好比告訴機器這是一個 XX 頻道,那麼機器自動能分析母嬰頻道的主力消費人羣類型,而後針對這我的羣類型去推薦最合適的內容。好比假設咱們要搭建一個母嬰頻道,機器會自動基於母嬰頻道主力消費人羣是寶媽,而寶媽養娃最痛苦的是需求商品種類繁多、同時質量擔憂得不到保證,所以給她推薦內容導購爲主,同時穿插着一些品質上的背書好比用戶評價、品牌保證、平臺服務等等。

所以,咱們可能須要一個三層的模型:

一、第一層基於不一樣的內容,找出最合理的UI界面來進行展現,也就是智能UI模型。

二、第二層則是須要產出這些內容,這裏分了三個維度:行業&平臺+品牌&店鋪+貨品。

  • 針對行業差別化的訴求,行業運營決定這裏須要展現的行業內容的類型和形式,好比剛纔說的權益帶商品的模式,那麼就要經過行業表達模型找到最合適的權益以及結合這個權益之下最合適的貨品;
  • 針對純粹的商品展現,則是將人貨場的匹配作到極致,找到這個用戶目前最想要的商品;
  • 針對品牌&店鋪,品牌須要塑造品牌在消費者側的心智,對應的品牌會有本身的表達,好比品牌想要將一個新品打形成爆款,那麼對於這個爆款的打造就須要一個品牌表達模型來輔助他們運營;

三、第三層則更爲複雜

  • 行業內容模型其實就是行業運營經驗的沉澱,將運營目標具像成不一樣的場景,再將該場景下的運營經驗具像化成內容,這裏就須要行業側各類類型的內容做爲輸入,而模型則須要基於以往的各類組合後的運營經驗,給出最合適當前場景的內容組合;
  • 品牌內容模型也是相似的,整合吸取品牌在整個淘系體系下的各類資源投放,爲品牌&店鋪的運營提供一些行之有效的運營建議(推薦模塊),提高品牌運營的效率,下降運營成本;
  • 對於人貨匹配則是再拆分了三個模型,分別去處理貨品、場景和用戶;

貨品模型:從貨品中提煉出貨品中的最吸引人的一些特質,好比賣點、好評、銷量,以及將貨品結構化,方便貨品在不一樣的地方展現;

場景模型:基於用戶的實時行爲來定義當前用戶的購買場景,他可能想買一臺電視因此瀏覽了不少電視,抑或是在一家賣電視的專賣店裏面找同型號線上價格,抑或是在過年準備給父母購置一臺電視做爲年貨等等;

用戶模型:基於用戶的歷史行爲,將用戶劃歸某個類型的人羣,進行人羣精細化運營。好比一個用戶常常購買年輕人的潮流酷玩,但每到父親母親節或者特定時間就會購買一些長輩禮物的品類,說明是個有孝心的boy/girl,那麼針對這類孝順寶寶就能夠在不一樣的節日或其餘重要日子推薦一些給長輩送禮的內容

那麼咱們都有哪些數據呢?

  • 行業&平臺:行業有本身的沉澱,平臺有各類營銷玩法
  • 品牌&店鋪:品牌一樣有主打新品、限時優惠、專題活動、線下門店等等
  • 貨品:各類商品沉澱下來的屬性、評價、賣點等等
  • 用戶離線:用戶的各類行爲歷史,以及手動收集的一些用戶檔案
  • 用戶實時:好比它最近的一些行爲,從哪進入頁面,在什麼地理位置,什麼時間點

One More Thing

因爲咱們不是活在將來,所以沒法判定前端的將來究竟是怎樣的,但前端不會中止對於將來的探索。而這個將來不僅是技術的將來,也是業務的將來。技術和業務是咱們前進的兩條腿,業務的訴求推進技術邁向新的高度,而更先進的技術也爲業務帶來更多的想象空間。

若是你不想再沉溺於過去,不想再埋頭作爲業務切頁面的工具人,那就加入頻道與 D2C 智能團隊吧。有意向者請發送簡歷到 :tianxiang.wly@alibaba-inc.com



本文做者:王令宇(天鑲) 

閱讀原文

本文爲雲棲社區原創內容,未經容許不得轉載。

相關文章
相關標籤/搜索