作者 | 優酷前端技術團隊
在2017年底,優酷隻有Passport和洋芋的部分頁面用Node.js,PC和H5核心頁面還都是PHP模闆渲染。而最近2年,基于阿裡巴巴的技術體系,我們對PC、H5多端進行了技術改造。在2019年,React SSR第一次且成功地扛起雙11重任,具有一定意義。

本文将對這一技術演進之路進行總結和展望,有2點突出變化:
1) 我們将優酷C端核心頁面全部用Node重寫,完成了PHP到Node.js的遷移。在沒有PHP同學的情況下,前端可以支撐業務;
2)從Bigpipe+JQuery到React SSR,性能明顯提升。PC頁面首屏渲染降到150ms、播放器起播時間從4.6秒優化到2秒。H5站上了React SSR後,性能提升3倍。
演進之路
優酷前端團隊在之前 PC 首頁/頻道頁面改造的基礎上,将 React 服務端渲染沉澱出了一個技術架構,該項目已經在 Github 開源,截止目前已有 900+ star,具體使用方式和源碼請檢視egg-react-ssr
項目位址。
第一版:Bigpipe + jQuery
核心還是采用Bigpipe + Nunjucks模闆編譯實作的。模闆tpl和data編譯,生成html,這個部分其實Biglet的render方法裡做的。然後在請求寫入的生命周期上,将html分塊寫入浏覽器。
1)采用Bigpipe有2大核心優勢:
- 相容IE6等低版本浏覽器,不得不用。現代Web架構隻支援主流浏覽器。之前開發對jQuery都比較熟悉,二者結合是當時最完美的選擇;
- 業務屬性決定的,新老接口拼湊(PHP的,Java的,HTTP的),采用Bigpipe,利用Node.js并發,将接口請求從前端轉移到服務端,即可以保證業務快速疊代,也可以保證頁面性能;
将頁面進一步抽象,以前了解是每個子產品都Biglet。但實際使用中,進行分級處理會更好。
- 首先渲染布局;
- 核心:渲染首屏,對于播放頁重點是播放器和劇集内容;
- 其他:看不到的可以偷偷加載,及時不展示也沒問題;
2)性能
目前:React SSR
采用React SSR,是在Node.js Bigpipe做了一些之後才考慮的。穩定性有了,低版本浏覽器相容有了,接下來就要考慮團隊成長和架構更新的問題。
- 會JQuery,不會React,大家是非常想用想學的;
- Bigpipe雖好,但依賴模闆編譯,在記憶體和CPU使用上非常高,優化不易;
- 老系統慢慢下掉,之前混着新老接口一起用的方式也需要重新梳理。為了快速疊代而産生的“狗糧”還是要吃的;
其實,如果把React當模闆,結合Bigpipe,可以達到和之前解決方案一樣的效果。問題不能很好的利用React的優勢,React自身也提供SSR基本能力。是以,我們需要做的是如何結合React的SSR,建構出符合業務特點的SSR架構。
元件級同構: 支援 CSR/SSR 一鍵切換
在技術調研期,我們分别看了next.js和easywebpack。
- easywebpack在使用上,我不認可使用egg的worker來做。easy-team的方案本地開發采用了在Node中啟動webpack編譯bundle的方案,将服務端bundle打包在記憶體中,agent程序通過memory-fs提供的api來讀取檔案内容,并且通過worker與agent程序的通信,來讓worker程序可以擷取到檔案的字元串内容。然後采用了Node的runInNewContext api,類似于eval的方式去執行js字元;
- next.js寫法上是完美的。結合上面講過的Biglet,請求方法抽取成靜态方法,可以複用。另外在服務端渲染,先執行請求方法,是最高效的方式;
寫法上,最終定了采用next.js式的寫法。
該技術方案具有以下優點:
- 實作方式簡單優雅
- SSR/CSR 無縫切換
- 全面擁抱 JSX
- 擁抱阿裡生态
我們的代碼既可以在服務端運作又可以在用戶端運作。這裡需要重點講一下CSR和SSR,我們是業内第一個這樣做的。它也帶給我們一個意外驚喜,那就是在服務降級上提供了一個更好的方案。
播放頁的服務支援兩種渲染方式,當服務端有渲染壓力時或叢集不穩定時,可以切換為用戶端渲染,服務端隻負責頁面的 SEO 資料擷取,渲染工作交給浏覽器。另外一種方式是當資料源服務出現問題時,可以使用 CDN 資料兜底進行頁面容災。
3元件: 多子產品更新配合改造
播放頁的頁面元件包括首屏、分發區、彈幕、播放器、評論等等一系列的元件,此次播放頁更新對應的元件也做了重構,其中彈幕、評論已随新版播放頁一起灰階上線。
服務端 JSBundle 釋出: 變更無需釋出應用
在 SSR 改造中我們總結出了一套基于配置下發的服務端和用戶端檔案的流程。該流程有以下優點:
- 建構方式一緻
- 釋出方式一緻
- 服務端 bundle 變化無需走服務端釋出
- 及時生效
下面是釋出的流程圖:
性能對比
以預發版本播放頁為例,使用 chrome 無痕模式測試。
優酷PC播放頁:150ms首屏,首屏文檔大小37kb。文檔到達時間平均為 120ms。
優酷H5播放頁性能提升3 倍。
未來:Serverless SSR
從beidou、next.js、egg-react-ssr到Umi SSR,可以看出服務端渲染是很重要的端側渲染組成部分。無論如何,React SSR都是依賴Node.js Web應用的。那麼,在Serverless時代,基于函數即服務(Functions as a Service,簡寫為FaaS)做API開發相關是非常簡單的:1)無服務,不需要管運維工作;2)代碼隻關系函數粒度,面向API程式設計,降低建構複雜度;3)可擴充。
在FaaS下,如何做好渲染層呢?直出HTML,做CSR很明顯是太簡單了,其實我們可以做的更多, Serverless時代的渲染層具有如下特點:
- 采用next.js/egg-react-ssr寫法,實作用戶端渲染和服務端渲染統一;
- 采用Umi SSR建構,生成獨立umi.server.js做法,做到渲染;
- 采用Umi做法,内置webpack和React,簡化開發,隻有在建構時區分用戶端渲染和服務端渲染,做好和CDN 配合,做好優雅降級,保證穩定性;
- 結合FaaS API,做好渲染內建。
通過提供ctx.ssrRender方法,讀取dist目錄下的Page.server.js完成服務端渲染。
核心要點:
- ssrRender方法比較容易實作;
- 采用類似Umi SSR的方式,将源碼打包到Page.server.js檔案中;
- 在釋出的時候,将配置,app.server函數和Page.server.js等檔案上傳到Serverless運作環境即可。
綜上所述,我們大緻可以推出架構更新的4個階段。
- 在CSR中,開發者需要關心React和webpack;
- 在SSR中,開發者需要關心React、webpack和egg.js;
- 在Umi SSR同構中,開發者需要關心React和egg.js,由于Umi内置了webpack,開發者基本不需要關注webpack;
- 在未來,基于FaaS的渲染層,開發者需要關心React,不需要關心webpack和egg.js。
在這4個階段中,依次出現了CSR和SSR,之後在同構實踐中,對開發者要求更高,甚至是全棧。所有這些經驗和最佳實踐的積累,沉澱出了更簡單的開發方式,在未來Serverless環境下,希望前端更加簡單、高效。
規範
實作
生态
緻敬所有多端堅守者
感謝蘋果,将使用者體驗提升到了前無古人的位置。移動網際網路興起後,PC Web日漸沒落。在AI時代,沒有“端”的支援可以麼?明顯是不可以的。不隻是“端”的概念,而是真真正的使用者體驗。
1)我們可以利用PC/H5快速發版本的優勢,快速驗證AI算法,繼而為移動端提供更好的模型和資料上的支撐;
2)多端對齊,打好組合拳。既然不能在移動端有更大的突破,大家隻能在細節上血拼。按照木桶原理,哪個地方是短闆,整體水位就在那裡。
今天的大前端,除了Web外,還包括各種端,比如移動端、OTT,甚至是新的物聯網裝置。我們有理由相信Chrome OS當年的遠見:“給我一個浏覽器,我就能給你一個世界”。
好書推薦:
前端代碼是怎樣智能生成的
關注「Alibaba F2E」
回複 電子書,立即下載下傳