導讀:做者從 17 年雙十一前開始接手天貓搜索前端,開發第一個需求—— H5 湊單頁,到今天已經將近兩年了。在這兩年裏,天貓搜索的前端體系發生了比較大的變化。今天分享一篇階段性的總結文章,記錄天貓搜索前端技術的過去、如今,以及本身做爲業務目前的惟一前端對將來的思考。
大致劃分css
首先基於前端技術的演進,大致上能夠將天貓搜索前端的發展歷程和將來趨勢總結成幾個時代:前端
之因此這麼劃分,主要是基於天貓搜索的前端技術方向以及天貓乃至淘系前端技術體系發生的較大變化。而在這其中能夠再提煉時代的關鍵詞:react
下面就來介紹各個時代天貓前端的技術狀態和一些思考。webpack
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 ,交叉修改時有發生。模塊間的通訊也是直接調用模塊實例方法來實現,模塊耦合很是嚴重。
▐ 小結
由此能夠看到那個時代最主要的問題有以下幾個:
隨着智能手機的普及,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 搜索時代的問題:
但隨着業務的發展,依然發現有一些問題:
在 all in 無線的大環境下,因爲搜索結構較爲固定、無線端開發資源較爲充裕等等各類緣由,天貓搜索業務在端內徹底被 Native 承接,而 H5 更加註重端外和站外。這也致使了 H5 搜索的業務能力和 Native 脫節,僅保留核心篩選功能以及喚端功能。所以 H5 搜索很長一段時間幾乎沒有前端資源投入,而在 2017 年 8 月左右因爲組織架構調整,我手上的天貓商品業務交接後,我開始逐步接手天貓搜索前端業務。而我要作的第一個需求,就是一個包含 H5 搜索 80% 功能的 H5 搜索湊單頁。
▐ 技術方案
模塊化
我和團隊同窗採用 Preact + MUI 5 方案來實現,MUI 5 其實就是 MUI 4 的升級,採用 CommonJS 的寫法來編寫模塊,再通過構建工具編譯封裝生成 AMD 模塊。其實當時會場已經大規模採用 Vue Weex 了,那咱們爲何要採用 Preact 呢,主要是基於以下幾點考量:
所以在這個階段,咱們使用 Preact 作了不少的搜索周邊的功能頁面,如上面提到的 H5 湊單、還有貓搜的領券彈層、湊單領券頁面、搜索分類頁面等等。
頁面渲染
因爲 Preact 的異步渲染特性,頁面渲染咱們直接拋棄了應用,而是採用斑馬源碼頁面的方式。這樣的好處是,前端再也不須要和 aone 頻繁的打交道,服務端只須要封裝一個 mtop 接口給前端,前端在斑立刻建立基礎 HTML 引入資源並調用接口獲取數據渲染便可,前端本身徹底掌控了調試、開發節奏。因爲對於應用的依賴僅限於一個 mtop 接口,所以前端能夠提早定好數據規範,在服務端開發接口的同時基於本地調試工具進行 mock ,大大下降了聯調成本。
模塊管理
React 生態有很是多的模塊管理方案,咱們調研過的 Flux、Redux、Reflux 等等均可以知足咱們的需求。但通過仔細的思考咱們選擇直接擼,不使用任何框架來管理模塊通訊。如此考量的緣由主要遵循以下理念:
▐ 小結
引入 MV* 框架後,咱們的技術方案又獲得了一些提高:
這裏仍是有一些問題:
借鑑天貓超市極致 H5 經驗,搜索在分類頁作了很是多性能優化嘗試,好比:
一、代碼優化
二、DNS優化
三、接口優化
四、埋點優化
五、加載優化
六、體感優化
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 的技術方案。前端的開發流程就變成了以下:
頁面渲染
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 模塊中,如:
▐ 小結
通過了 Weex 時代,咱們的技術又獲得了提高:
但這裏仍是有幾個問題沒有解決:
至此咱們能夠發現,如今搜索前端核心解決的問題逐漸變成了共建和規模化了,再也不是以前單純前端技術問題了。既然要解決共建和規模化,咱們能夠看看規模化成功的一個典型例子:會場。過去會場也是一個個頁面前端人肉開發,到後來有了斑馬就能夠由運營模塊化搭建了,前端只須要開發一些基礎模塊就能夠知足全部行業的訴求,多麼的美好!那麼搜索是否是也能搭建呢?
答案是:「是的」,但畢竟場景不一樣,咱們不能和會場同樣樓層 duangduang 地堆砌,爲何呢?
首先在場景的層面有比較大的不一樣。在用戶進入這個會場時,已經決定了當前的場景了,一個會場頁面就是一個場景,所以在這個會場頁面下,只須要圈出這個場景的模塊就能夠了。而對於搜索,全部的場景都須要在搜索這一個頁面展現,而在搜索如何定義一個場景呢?
這麼多維度,一個或多個交織在一塊兒才定義了一個場景,而在這個場景下會展現一個或多個模塊。
以 Query 舉例:
固然,會場模塊裏面的貨品徹底能夠多樣化,另外如今會場基於袋鼠也有千人千面模塊的能力了,這裏是拿以前的會場作例子
基於這樣的思考,搜索啓動了一個長頸鹿項目,以以前搜索域就有的一個產品——品牌 Minisite 做爲切入點,爲品牌商提供了一個全新的品牌運營陣地
如上圖,從左往右分別是三個版本的 minisite 。這裏能夠看到, Minisite 做爲品牌在搜索的一個搭建陣地,一直採用的是提供模塊讓品牌商填入數據的玩法。品牌商自定義程度很低、維護慾望很低,所以導購效率一直不高。而在長頸鹿項目中,搜索在商品列表層之下又新開了一個層,在這個層裏展現一個品牌商家搭建的頁面,在這個頁面中品牌商家能夠充分的自定義。而對於一個跨品類經營的大品牌,咱們也開放了品牌詞+主營類目詞的組合,方便其對每一個主營類目去搭建本身的頁面。
而在品牌詞下取得成功後,咱們將能力擴展到了行業側,在搜索中臺——美高上建設了心智造產品。讓行業也能夠基於一樣的方式去經營品類詞,搭建行業本身的頁面。
心智造和 Minisite 分別是針對品類詞和品牌詞,相互不會交叉。而對於一些橫跨多品類的平臺級需求,好比一些頻道相關的需求和拉新相關的需求,是很是容易與其餘場景交叉的。爲了解決這個問題,咱們在美高上沉澱了一套模塊定投方案——無界,經過模塊級別的投放,讓場景之間的交叉變成可能,只須要簡單定義模塊展現的規則,就能讓不一樣場景的模塊展現在同一個頁面上。
▐ 技術方案
模塊化
首先是心智造和 Minisite ,它們的核心技術方案是類似的——都是採用千葉(一個給商家用的頁面搭建平臺)做爲模塊搭建平臺,並在千葉的搭建能力之上,包裝了一層頁面投放策略的管理。其實到這裏,模塊化方案和會場並沒有二致,只是模塊的實現採用了 Prax 來兼容 Weex 和 H5 :
一、編碼階段
二、渲染階段
而到了無界,這些就徹底不 work 了。畢竟無界是走的模塊級定投,容器只有一個,所以投放場景極可能和心智造、 Minisite 場景交叉:
而咱們採用了以下技術方案將無界的定投模塊插入到頁面中:
經過這樣的方式,最終渲染出當前場景下全部的模塊內容。另外在無界後臺咱們有一套場景干預規則,解決場景交叉時進行一些手動干預。與此同時咱們還提供了一套動態數據源機制,方便三方 HSF、TPP 數據能直接綁定到模塊上,實現模塊和數據解耦。
頁面渲染
頁面渲染如上述所示,依舊是經過斑馬。但與以前不一樣的是:
因爲是模塊化搭建,頁面經過 PI 統一管控,頁面渲染依賴 PI 行爲控制
對於長頸鹿容器,一樣是 Native 建立 Weex 容器渲染,但與以前渲染一個僅包含一個模塊的 Weex 頁面顯然是不一樣的,長頸鹿容器內渲染的也是一個真正的模塊化搭建的頁面
對於無界定投的模塊,提供了插入機制,解決了場景交叉時的展現問題
模塊管理
對於頁面內的通訊,因爲頁面經過 PI 統一管理,也就意味着模塊的各類能力都須要依賴 PI 來進行實現。因爲這樣的樓層搭建通常通訊結構都是扁平的,因此基本上經過模塊冒泡給 PI , PI 下發給對應模塊便可。不過通常不建議模塊之間進行通訊。
對於頁面和容器通訊,咱們是在 PI 中提供了一些封裝的能力,另外也能夠本身調用容器提供的方法,與 Native 內嵌坑位的 weex-module 方案別無二致。
▐ 小結
因爲長頸鹿內的技術方案已經脫離傳統意義上的前端,更多設計客戶端和服務端,是整個產品架構的設計,這裏很難講清楚,放一張圖可能清晰一點:
這裏前端技術又有了提高:
但這裏咱們仍是有幾個問題還沒有解決:
搜索最擅長的顯然就是搜索結果頁那種商品瀑布流,將用戶最想要、最有可能購買的商品推薦給他們。而這個能力也能夠複用在諸如首頁、頻道、店鋪、專輯等等地方。而當咱們要在不少不一樣的地方去搭建這樣一個列表頁時,在上面所說的樓層搭建中,咱們通常會怎麼作呢?
若是這麼處理,若行業大面積規模化,會出現以下幾個問題:
這些顯然都是咱們不肯意看到的,咱們將組件的不一樣場景徹底剝離,能夠發現一些規律:
進一步提煉:
因此咱們有沒有可能在這個理念上更深一步進行搭建呢?
模塊化
答案顯然是有的,深度搭建的概念其實就是用來解決這種問題。將頁面上的模塊基於功能進行了從新定義:
經過這樣子的劃分,容器模塊控制了交互、展現模塊控制了 UI 、數據模塊控制了業務邏輯,好比一個包含篩選、商品流的列表更具體用 React hooks 來講就是:
合理的場景劃分相當重要,不一樣業務場景應該是數據模塊+容器模塊+展現模塊的組合,大多數狀況下容器模塊和展現模塊能夠複用,但數據模塊都是須要從新開發的。儘量讓數據模塊來適配容器模塊和展現模塊,不改變交互就不改變容器模塊,不改變UI就不改變展現模塊。
在這裏模塊的編寫切換到了 Rax 1.0,與會場的開發方式一致以實現複用。Rax 1.0 針對 Web 作了不少優化,打出來的 bundle 也更加輕量,性能也好了不少,已成爲天貓前端業務開發主要方式,所以再也不須要使用 Prax 了。
頁面渲染
這裏和傳統搭建有個很重要的不一樣,模塊之間出現了關聯關係。好比以下關聯:
那麼咱們就須要一個全局方式來處理這些關聯。首先須要在搭建模塊的時候去指明模塊之間的關聯關係,好比我本身是定義了三個字端:
data 和 container 都是二段結構的,好比 data 的 a:b 表明使用 key 爲 a 的數據模塊的 b 字端內的數據,而 container 的 a:b 則表明使用key爲a的容器模塊,並將本身做爲其 b 區域的展現模塊使用。
這幾個字端都會在腳手架裏,初始化時生成到 schema.$attr 中。而真正負責識別這些字端並將模塊串起來的天然是頁面初始化腳本—— PI ,PI 幹了以下事情:
模塊管理
這裏模塊的通訊有兩種,一種是基於公用數據模塊的通訊,一種是基於 PI 的通訊。
一個頁面上能夠有多個數據模塊,而每一個數據模塊均可以對接到多個容器/展現模塊(這也是爲何 data 是二段結構的緣由)。所以當多個模塊須要通訊的時候,能夠經過dispatch觸發數據模塊行爲,數據模塊刷新數據影響另一個模塊。
基於PI的通訊通常都是針對一些特殊場景,好比一個很經典的例子——篩選列表篩選欄變形吸頂:當頁面有不少模塊,篩選列表並非全屏大小而是跟着整個頁面一塊兒滾動,當篩選欄滾出視野外,它須要變成一個相對簡單的結構吸頂。在這種場景下,因爲吸頂層自己是一個絕對定位的層,而頁面文檔流也是一個層,兩個層之間不基於 DOM 操做的話,最合理的方式就是基於一個數據模塊進行狀態共享。如吸頂組件定義了吸頂時的樣式和正常的樣式,而且暴露一個建立數據模塊的方法, PI 在渲染吸頂組件時會單獨爲其建立一個數據模塊來共享篩選欄狀態。
▐ 小結
爲何要搞的這麼複雜?其實就是但願能將 UI 和交互作的更加純粹,當 UI 和交互都是針對單一場景、足夠簡單的時候,咱們就能引入一些產品來進行提效,好比:
經過這這樣的方式,最終頁面上大多數內容都變得能夠複用,規模化的成本也就大大下降了。
因爲搜索還在深度搭建時代探索,如下是我基於團隊方向 YY 的,但我相信這個時代很快就會到來
但上述的各類方式終究仍是人肉的,須要人力投入的。既然工具能讓咱們以配置的方式解決交互和 UI ,那麼有沒有可能連配置都不須要,機器自動幫咱們生成一個數據模塊或者交互呢?
這就是咱們團隊正在作的,目前團隊的同窗正在嘗試基於機器學習訓練模型實現智能化UI。只須要給出一些關鍵信息(好比要展現商品的哪些字端),就會自動化的生成對應的展現模塊或交互模塊。這些模塊使用到深度搭建之中,前端就只須要經過數據模塊定義展現的內容來源就能完成整個頁面的搭建。實現UI零成本。
而咱們進一步擴展去思考,把大象裝冰箱分爲三步,那麼把搜索智能化應該也只須要三步:
具體一點多是:
所以,咱們可能須要一個三層的模型:
一、第一層基於不一樣的內容,找出最合理的UI界面來進行展現,也就是智能UI模型。
二、第二層則是須要產出這些內容,這裏分了三個維度:行業&平臺+品牌&店鋪+貨品。
三、第三層則更爲複雜
貨品模型:從貨品中提煉出貨品中的最吸引人的一些特質,好比賣點、好評、銷量,以及將貨品結構化,方便貨品在不一樣的地方展現;
場景模型:基於用戶的實時行爲來定義當前用戶的購買場景,他可能想買一臺電視因此瀏覽了不少電視,抑或是在一家賣電視的專賣店裏面找同型號線上價格,抑或是在過年準備給父母購置一臺電視做爲年貨等等;
用戶模型:基於用戶的歷史行爲,將用戶劃歸某個類型的人羣,進行人羣精細化運營。好比一個用戶常常購買年輕人的潮流酷玩,但每到父親母親節或者特定時間就會購買一些長輩禮物的品類,說明是個有孝心的boy/girl,那麼針對這類孝順寶寶就能夠在不一樣的節日或其餘重要日子推薦一些給長輩送禮的內容
那麼咱們都有哪些數據呢?
One More Thing
因爲咱們不是活在將來,所以沒法判定前端的將來究竟是怎樣的,但前端不會中止對於將來的探索。而這個將來不僅是技術的將來,也是業務的將來。技術和業務是咱們前進的兩條腿,業務的訴求推進技術邁向新的高度,而更先進的技術也爲業務帶來更多的想象空間。
若是你不想再沉溺於過去,不想再埋頭作爲業務切頁面的工具人,那就加入頻道與 D2C 智能團隊吧。有意向者請發送簡歷到 :tianxiang.wly@alibaba-inc.com
本文爲雲棲社區原創內容,未經容許不得轉載。