作者 | 狼叔
由於BFF升級到SFF,除了享受Serverless基建的好處外,並沒有任何業務價值的改變,所以核心只能在提效上發揮。提效第一點是開發者體驗,這是Serverless託管前端所有場景的核心提效點。其次是搭建,搭建和Serverless託管、前端工作臺集合,可以讓SFF提效更容易。中間對流程編排、智能化也有結合,相信大家能夠理解它們的價值和應用場景。
搭建、流程編排、智能化組合提效,簡化Serverless託管提效,讓前端進入輕研發時代,我相信已經不遠了。下面分享一下我關於Serverless新託管時代的暢想。
JAMS
從lamp到mean架構升級,之後就沒啥新東西了。在Egg穩定之後,也是沒有啥新意了,就算Fastify也不夠亮眼,實話講,那點性能優化不過錦上添花,還不一定趕上Node sdk升級的優化呢。
JAMstack算是一個比較新的概念,JAM是JavaScript、API和Markup的簡稱,前面第一個字母縮寫,JAMstack一種基於客戶端JavaScript,可重用API和預構建Markup的現代Web開發架構,這個價值在業界已經證明了,那麼基於serverless的JAM,應該也是值得想象的。
本節核心內容是把JAM進行延展並推到JAMS的可能性。
什麼是 JAMstack
JAMstack是指使用JavaScript、API和Markup構建的技術堆棧,需要符合下面三個標準:
- JavaScript:請求/響應週期中的任何動態編程都由JavaScript處理,完全在客戶端上運行。這可以是任何前端框架,庫,甚至是輕量JavaScript。
- API:所有服務器端進程或數據庫操作都被抽象為可重用的API,使用JavaScript通過HTTPS訪問。這些可以是定製的或利用第三方服務。
- Markup:模板化標記應該在部署時預先構建,通常使用內容站點的站點生成器或Web應用程序的構建工具。
當我們談論“堆棧”時,我們不再談論操作系統,特定Web服務器,後端編程語言或數據庫。JAMstack與特定技術無關。這是一種構建網站和應用程序的新方法,可提供更好的性能,更高的安全性,更低的擴展成本以及更好的開發人員體驗。
為何選擇JAMstack?
- 更好的性能:為什麼要在部署時生成頁面時等待頁面動態構建?當談到最小化第一個字節的時間時,沒有什麼能比通過CDN提供的預構建文件更好。
- 安全性更高:將服務器端進程抽象為微服務API,可以減少攻擊的表面區域。您還可以利用專業第三方服務的專業知識。
- 更便宜,更容易擴展:當您的部署相當於可以在任何地方提供服務的一堆文件時,擴展就是在更多地方提供這些文件的問題。CDN是完美的,通常包括擴展他們的所有計劃。
- 更好的開發者體驗:鬆散耦合和控制分離允許更有針對性的開發和調試,並且為站點生成器擴展選擇CMS選項消除了為內容和營銷維護單獨堆棧的需要。
redwood.js
Redwood是一個全棧、無服務器的Web應用程序框架,它使您可以輕鬆地構建和部署JAMstack應用。https://redwoodjs.com/tutorial/redwood-file-structure
很明顯,這是一套很潮的技術棧,但問題是組件的ui和邏輯如何抽離?這個問題依然沒有解決。
對於GraphQL真是又愛又恨,基於模型(實體)和查詢(Query)的方式,很好的做到了解耦,但這東西基於約定寫法,必然會像Restfull api一樣,都是好東西,但在落地方面不會很理想。
GraphQL如何能夠和Formily進行集成,在模型和Schema/Form之間互轉,可以想象的空間會尤其大。
重新定義 JAMS
之前JAMStack缺點
- 缺乏對較重和動態功能的良好支持:使用 JAMStack 的主要限制之一是它不能很好地處理電子商務購物和登錄等更加動態的功能。這是因為這些功能需要數據庫才能管理交易。
- 高度依賴第三方系統:高度依賴第三方系統意味著如果這些系統崩潰,那麼 JAMStack 也會崩潰。
如果把CDN換成Serverless呢?將Serverless作為託管環境,API和頁面都以函數的粒度放到Serverless上進行託管,是不是很好?
- 動態功能完美解決
- 依賴第三方系統也可以通過baas來解決
JAMStack on Serverless可以是JAMS,核心內容如下
- JavaScript:基於 JavaScript 創建動/靜態 Web 應用。
- APIs:所有的數據行為通過可複用的 HTTP 接口(RESTFul 或者 GraphQL)完成。
- Mockup:使用構建工具 prebuilt 前端應用,部署到 Serverless 環境,能夠同時支持csr和ssr。
- Serverless:利用Serverless基建優勢,提供自動擴縮容零運維的Api和頁面託管服務。
Jeff Atwood發表於2007年的這篇博客裡,他提出了著名的“Atwood定律”,即”任何能夠用JavaScript實現的應用系統,最終都必將用JavaScript實現。
在JAMS世界裡,Atwood定律又一次完美的被證明了。
應用場景
JAMS是面向函數的Fullstack架構。它的應用場景包含了前端和sff的所有場景。
1、Zeit應用場景
2、Serverless CMS https://github.com/webiny/webiny-js
Serverless CMS (GraphQL + React + Node.js + AWS Lambda)
More Than “Just” a CMS:Build Websites, Apps and APIs With Webiny
As a Developer You Will Benefit From Several Features
- Comes with an admin theme with over 30 React components
- Built-in server side rendering
- CSS-in-JS via Emotion
- Deployment CLI with support for multiple environments
- Foundation for building dynamic serverless sites and apps
- Designed and optimized to run inside AWS Lambda
總結一下,整體上大家除了對CSR和SSR做同構上,沒有做到極致外,這套方案還是非常ok的。接下來,基於Serverless,補足託管能力,JAMS會有更好的發展。
Serverless 新託管時代
類似於surge.shgit pages類似的託管服務很多,那麼基於Serverless如何做託管呢?筆者如何定義Serverless新託管時代便是本節要重點聊的內容。
從 BFF 之痛到 SFF 收斂
瞭解託管之前,我們先看一下架構升級,從BFF到SFF的演進過程。
BFF即 Backend For Frontend(服務於前端的後端),也就是服務器設計 API 時會考慮前端的使用,並在服務端直接進行業務邏輯的處理,又稱為用戶體驗適配器。BFF 只是一種邏輯分層,而非一種技術,雖然 BFF 是一個新名詞,但它的理念由來已久。
在Node.js世界裡,BFF是最合適的應用場景。常見的API、API proxy、渲染、SSR+API聚合,當然也有人用來做網關。
從Backend For Frontend升級Serverless For Frontend,本質上就是利用Serverless基建,完成之前BFF的工作。那麼,差異在哪裡呢?
核心是從Node到FaaS,本質上還是Serverless,省的其實只是運維和自動擴縮容的工作,一切看起來都是基建的功勞,但對於前端來說,卻是極為重大的痛點解決方案,能夠滿足所有應用場景,基於函數粒度可以簡化開發,乃生死必爭之地。
Serverless簡單理解是FaaS+BaaS。FaaS是函數即服務,應用層面的對外接口,而BaaS則是後端即服務,更多的是業務系統相關的服務。當下的FaaS還是圍繞API相關的工作為主,那麼,前端如何和Serverless綁定呢?
Serverless For Frontend(簡稱SFF)便是這樣的概念,基於Serverless架構提供對前端開發提效的方案。
下面看一下SFF分工,這張圖我自認為還是非常經典的。首先將Serverless劈成2半,前端和後端,後端的FaaS大家都比較熟悉了,但前端頁面和FaaS如何集成還是一片待開發的新領域。
舉個例子,常見BFF的例子,hsf調用獲得服務端數據,前端通過ctx完成對前端的輸出。這時有2種常見應用場景
- API,同後端FaaS(RPC居多)
- 頁面渲染(http居多)
基於FaaS的頁面渲染對前端來說是必須的。從beidou、Next.js、egg-react-ssr到Umi SSR,可以看出服務端渲染是很重要的端側渲染組成部分。無論如何,React SSR都是依賴Node.js Web應用的。那麼,在Serverless時代,基於函數即服務(Functions as a Service,簡寫為FaaS)做API開發相關是非常簡單的,
- 1)無服務,不需要管運維工作
- 2)代碼只關係函數粒度,面向API變成,降低構建複雜度
- 3)可擴展
大概三國演義對我來說印象最深的一句話估計就是分久必合,合久必分。本質上sff和bff做的事兒是一樣的,如果說非要去掰扯出點東西,我想分久必合也算是一種吧。
通過 Fab 看託管
FABs(Frontend Application Bundles)是一種前端應用的bundle格式。
因為 FABs 包含了 server-side JavaScript 兼容能力,但可以非常簡單的同構上傳一個zip包文件就完成部署。你可以隨意增加server-side 邏輯且不需要關注服務器運維相關的複雜性。它適合如下場景。
- 發佈 server-rendered NextJS 應用到Cloudflare workers上
- 給cra創建react項目 增加 redirect 規則 ,不需要eject就能做到
- 使用 Gatsby 來生成logged-in 和 logged-out 主頁,並且可以cookie來切換登錄狀態。
- 保護你的應用,防止未授權用戶操作
- 發佈每個提交到一個唯一的URL來分享協作進度
- ...等等
它原理很簡單。FABs是一個特殊的zip文件,保護了1個組件和一個server-side JavaScript文件,以及靜態資源assets目錄。
對於純靜態站點,spa,或一個完全的服務器端渲染的js網站,FAB會幫你編譯你的應用到這2個文件。
看一下寫法
const getProdSettings = () => {
return {
// All production settings are bundled into the FAB here,
// ensuring predictable behaviour regardless of host.
// These are returned as a separate entry point, however,
// so that any encrypted variables can be decrypted
// by the host before being passed through to the render.
}
}
const render = async (request, settings) => {
// request: a fetch.Request object
// settings: your production settings plus any
// environment-specific overrides
const { body, statusCode, headers } = await myApp.render(request, settings)
// return a fetch.Response object with the full data.
// Streaming responses not yet supported, but will be in future.
return new Response(body, { statusCode, headers })
}
module.exports = { render, getProdSettings }
和我們定義的ssr規範的中寫法很像,原理上並沒有本質區別。
我們再來歪歪一下。一個server.js和assets目錄就可以滿足所有的前端場景。
- 純前端assets就夠了。
- server.js可以滿足所有bff應用場景,無論渲染,還是api proxy。server.js 是一個faas函數,可以隨時發佈到Serverless環境上。
相當於
- Serverless做了託管環境,幾乎不用管運維
- 開發時用法,如now.sh或surge.sh,絲般順滑
- 把ci/cd也接入進來,那麼linc.sh做的就是這個事兒
FAB的核心難點是打包。
FAB可以在任何地方構建,並且產出獨立的結果文件,可以有輸入集合,fab.zip是一個每個字節都相同的包,無論何時何地都可以使用。這是因為包含了deterministic-zip模塊,它從文件中刪除修改時間戳,這樣fab就會產生一致的結果了。
這意味著,在編譯FAB之後,包含內容用於發佈的Fab包擁有一樣的MD5/SHA 哈希值。不需要引入新的發佈,這是因為內容授權是一樣的。不需要觸發重新發布,當修改README.md 或端到端測試的時候。
這是很hack的技巧,但用起來確實會簡單。但還有一個問題沒解,就是node_modules是否需要打包的問題。打包到一個文件,會有加載性能問題,不打包就需要放到faas runtime裡。各有利弊。
按照fab的玩法,node_modules放到faas runtime裡,loader部分解析一下fab.zip執行就好了。這也是一個很好的做法。
抽象一箇中間格式,做到部署無關,確實是一個很棒的做法,示例如下圖。
我不管你用什麼技術棧,一個server.js和assets足夠用了,編譯你自己做,然後按照我的方式達成fab包。這就是你發佈時需要用的。剩下的就是發佈到faas環境即可。
我們一直在追求Serverless在提效領域的極致。當所有前端場景都可以做到極簡託管,在配套各種基建,輕開發模式,難道不值得當成夢想嗎?
來自競品的壓力和啟示
騰訊雲Serverless的做法,投資serverless.com,筆者以為是挾天子以令諸侯的感覺。站在標準之上,有意思的很。投資coding.net,我理解是對WebIDE等輕量級開發方面做資源整合,也是一步好棋。
這些都不重要,我們要看的是它的託管能力擴展實現。
它的component做法https://serverless.com/components/ 很一般,但很實用。
核心要點:
- 指定website目錄
- 提供一個函數
Serverless Components 是面向資源的設計,可擴展性極強。想AWS Lambda, AWS S3, Azure Functions, Google Big Query, Twilio, Stripe, Algolia, Cloudflare Workers 等都可以使用。大多數 Serverless Components 部署要傳統雲部署要快上 20倍。他們的意圖是設計Serverless Components 來做到最大程度的快速部署,移除本地對模擬網絡應用的依賴。
從這點上看,Serverless Components和fab的做法是一致的,都是把Serverless當做託管環境。不同的是fab要更極致一點。
接下來,集團內的Serverless也會圍繞託管做,推進的2個核心點。
- http serve實現,基於midway-faas很容易
- serverless-side render實現,基於egg-react-ssr設計,已開源
對於BFF裡的API、API Proxy這些都很容易基於FaaS搞定,對於前端關心的點,我的看法
- CSR要支持。把faas當cdn用,雖然Dirty,但對於中後臺或外包來說是有積極意義的。
- SSR必要時能支持。把FaaS當Node用。
- 如果能隨便切換更好。既要也要還要。
當然,ToC的場景和ToB的場景是有差別的,流量和成本成正比,必然會導致實現上的差別,這點在下一小結會講。
除此之外,now.sh或surge.sh,linc.sh這些在易用性上做的實踐是非常值得借鑑的。
Serverless-side render 會火
裕波曾在2017年問我,為何如此鍾愛SSR?我的回答如下。
從前端的角度看,它是一個相對小的領域。PC已經非主流,H5想爭王者,卻不想被 React-native、Weex 中間截胡。無論怎麼看,SSR能做的似乎都有限。但是,用戶體驗提升是永遠的追求,另外Web標準化是正統,在用戶體驗和Web標準之間,又要和 Node.js 做結合,除了SSR,想不到更好的解法。
貼著C端業務,從後端手裡接過來PC、H5,通過 Node.js 構建自己的生存之地是必然的選擇。活下來之後,就開始有演進、沉澱,通過C端業務和 egg-react-ssr 開源項目的沉澱,我們成功的打通2點。
- 寫法上的統一:CSR和SSR可以共存,繼而實現二種模式的無縫切換
- 容災降級方案:從Node SSR無縫切換到Node的CSR,做到第一層降級,從Node CSR還可以繼續降到CDN的CSR
2019年,另外一個風口是 Serverless,前端把 Serverless 看成是生死之地,下一代研發模式的前端價值證明。那麼,在這個背景下,SSR能做什麼呢?基於FaaS的SSR如何做呢?繼續推演,支持SSR,也可以支持CSR,也就是說基於FaaS的渲染都可以支持的。於是和風馳商量,做了Serverless端側渲染方向的規劃。
本來SSR是Server-side render,演進為Serverless-side render。元彥給了一個非常好概念命名,Caaf,即Component as a fuction。渲染層圍繞在以組件為核心,最終統統簡化到函數層面。
在今天看,SSR是成功的,一個曾經比較偏冷的點已經慢慢變得主流。
集團中,基於React/Rax的一體化開發,可以滿足前端所有開發場景。優酷側的活動搭建已經升級到Rax 1.0,對外提供SSR服務。在UC裡,已經開始要將 egg-react-ssr 遷移到FaaS上,代碼已經完成遷移。
- PC/中後臺,使用基於React的CSR和SSR可以滿足所有場景。
- 移動端/H5,基於 Rax 的CSR和SSR可以滿足所有場景。尤其是Rax SSR給站外H5提供了非常好的首屏渲染時間優化,對C端或活動支持是尤其有用的。
還有一個命題是值得聊聊的,即如何在Faas函數還不能保證4個9的情況下接入?
直接接入FaaS,依賴的Serverless的基建穩定性,目前應該還沒人敢保證4個9以上的穩定性。一個比較好的辦法是自建網關,好處有2。
- 對於歷史遺留問題,域名接入,反向代理等非常方便
- 在FaaS函數掛掉的情況下,可以降級到CDN託管
同一種寫法,既可以支持CSR和SSR,同時發佈到FaaS和CDN上,在網關上配置化容災策略,這樣做到3個9或4個9是很容易的事兒。
上圖右側是我們實現的新的基於ssr-spec和midway-faas的faas ssr實現 https://github.com/ykfe/ssr 。核心在Web目錄,同時支持多個頁面,且可以做到SPA和MPA在構建層做不同定製。目前Umi SSR、Ice SSR、Egg-react-ssr都是基於這套機制構建的,整體上看,這個方案是得到大家一致認可的。在FaaS SSR裡,會有更加極簡的用法,在降低開發難度上會進一步壓榨,期望能夠達到落地成本減半的目標。
在2020年,基於FaaS之上的渲染已經獲得大家的認可。另外大量的Node.js的BFF(Backend for frontend)應用已經到了需要治理的時候,BFF感覺和當年的微服務一樣,太多了之後就會牽扯到管理成本,這種情況下Serverless是個中臺內斂的極好解決方案。對前端來說,SSR讓開發變得簡單,基於FaaS又能很好的收斂和治理BFF應用,結合WebIDE,一種極其輕量級基於Serverless的前端研發時代已經來臨了。省了流程,少了運維,以後可以招人能降低,甚至外包,如果想做,後端的事兒也是能夠完成的,可以消掉前後端開發的開發分工。
自建 SFF 管理後臺會流行
針對於FaaS,前端能有的玩法。
- 函數管理,為ginkgo自帶功能,可以略微擴展,比如自定義網關集成中的path,url rewrite。
- 通用模板支持,由於場景不一樣,所以會提供serve,rpc/http,ssr,mock等多種類型的模板,對於開發者更加友好。
- 對外服務註冊。主要是來自服務市場的概念,很多函數如果想對外提供通用服務,通過設置,可以變為對外公共服務,可以變成其他函數的依賴,並在layer中可以按需注入。
- 快速場景定製,讓開發者感覺不到函數的存在,比如mock個json,那就直接輸入json和想訪問的地址,然後自動創建函數,發佈,訪問就好。
- 業務支持,基於以上4種細化的方案,做業務相關的開發。
當然,模式上也要考慮,比如c端和b端是不一樣的,主要差別在流量上(基建還不夠智能導致的)。一個典型的場景,在對內的bff裡,10個函數部署在一臺機器上會更划算,這時候除了樵楓大大的 EaaS(egg as a service:一個是機器成本的考慮,另一個是存量的大量Egg應用更平滑遷移到Serverless體系)這種Layer層面的定製外,能夠在平臺側提供聚合併發布的能力也是非常務實的功能。
講完FaaS玩法,你會發現所有的功能需要定製的還是非常多的,此時自建SFF管理後臺是非常必要的。
- 定製性更好,各個BU業務和研發習慣模式等都有不同
- 基於集團的Serverless基建,不需要考慮運維問題,有問題還是可以提需求
- 便於創新,目前基建已經提供了足夠的支持,讓開發更專注於開發
Serverless是風口,提效是有的,但業務價值沒有根本改變,所以圍繞開發者提效和創新才是核心。各個BU不去定製才是奇怪的事兒。
接下來大家發力的點,可能是下面這些。
- 圍繞網關做好穩定性,平臺基石
-
將Serverless做成託管容器,讓頁面託管/api託管更容易,目前看全場景落地沒問題的
- 內部bff應用,需要考慮流量問題,多函數一臺機器是強訴求,樵楓那邊的eaas,另外多函數如何compose成一個,類似於koa-compose這種,也是一個方向
- ssr和csr現有方案足夠,ice和umi都採用是這套
- 對於c端頁面,自建網關,在Faas函數掛掉的情況下,可以降級到CDN託管
- 關於函數的ctx,早晚還是要回歸到koa上,需求都上來,還是要通用,不然無法滿足,所有bff場景出現的問題都一定會在faas上出現。插件化也是faas的強訴求。
- 服務市場,現在實際已經成熟了。服務和路由要分開處理,讓沉澱服務變得更容易。
- 讓前端感知不到函數的存在,ui化,可視化,集成現在有的前端方案,做好生態
前端工作臺
前面講了,now.sh或surge.sh,linc.sh這些在易用性上做的實踐是非常值得借鑑的。這些所謂的易用性上的實踐集合在一起,你需要的其實就是前端工作臺。
Backstage is an open platform for building developer portals
https://github.com/spotify/backstage
理想麼?developer portals,不是frontend developer portals。這才是最重要的。
Backstagez已經在Spotify創建4年了。開源版本3個階段:
We created Backstage about 4 years ago. While our internal version of Backstage has had the benefit of time to mature and evolve, the first iteration of our open source version is still nascent. We are envisioning three phases of the project and we have already begun work on various aspects of these phases:
- 階段1: 擴展前端平臺 (正在做) - 讓你能夠簡單的為你的內部基建或工具創建一個一個單一的持久化UI層。可複用的UX模式和組件集有助於在工具之間保證一致的體驗。
- 階段2: 員工管理 (next 2-3 months) - Manage anything from microservices to software components to infrastructure and your service catalog. Regardless of whether you want to create a new library, view service deployment status in Kubernetes, or check the test coverage for a website -- Backstage will provide all of those tools - and many more - in a single developer portal.
- 階段3: 生態 (later) - Everyone's infrastructure stack is different. By fostering a vibrant community of contributors we hope to provide an ecosystem of Open
https://github.com/spotify/backstage/blob/master/docs/getting-started/create-an-app.md
app
├── README.md
├── lerna.json
├── package.json
├── prettier.config.js
├── tsconfig.json
├── packages
│ └── app
│ ├── package.json
│ ├── tsconfig.json
│ ├── public
│ │ └── ...
│ └── src
│ ├── App.test.tsx
│ ├── App.tsx
│ ├── index.tsx
│ ├── plugins.ts
│ └── setupTests.ts
└── plugins
└── welcome
├── README.md
├── package.json
├── tsconfig.json
└── src
├── index.ts
├── plugin.test.ts
├── plugin.ts
├── setupTests.ts
└── components
├── Timer
│ └── ...
└── WelcomePage
└── ...
目前能看到的是大型應用插件化,具體和portal做的集成度有多高,還沒有簡單。
前端工作臺:集前端現有功能,構建好用的前端門戶。核心技術應該是:微前端 + JAMS + 搭建。
- JAMS:基建,當下最潮的解決方案
- 微前端:在工作臺構建上擁有絕對重要性。Web 技術發展到今天,已經有大量存在時間數年乃至十年以上的巨石應用出現,技術的迭代往往導致技術債過高,拖累研發效率,貿然追進最新技術棧又會導致技術稅的繳納。微前端的出現給了這些項目一個進化和保持不進化的可能性。在 SPA 這一政治正確的技術方案外打開了一個新領域,也在這個領域相應開源了 qiankun 和 icestark 等項目。
- 搭建:最容易落地的提效手段
- 智能化:imgcook從d2c,到數據綁定,到p2c,能做的事兒其實也是為搭建服務的。未來可以想象的空間很大,是創新,結合搭建最容易落地,但不是必選項。
總結
FaaS場景下的SSR框架已經添加到阿里云云開發平臺的默認解決方案當中。結合阿里雲的CloudIDE功能,我們可以所有的開發,發佈操作都在雲上完成無需本地配置開發環境,使用起來十分的方便。
我姑且說之,你姑且聽之。如果說某些觀點能夠有點啟發,一起交流。對於未知的探索,需要有更多人一起來。
最後,分享一首我非常喜歡的舒婷《獻給我的同代人》,共勉。
他們在天上
願為一顆星
他們在地上
願為一盞燈
不怕顯得多麼渺小
只要盡其可能
唯因不被承認
才格外勇敢真誠
即使像眼淚一樣跌碎
敏感的大地
處處仍有
持久而悠遠的回聲
為開拓心靈的處女地
走入禁區,也許——
就在那裡犧牲
留下歪歪斜斜的腳印
給後來者
簽署通行證
1980.4
文末福利
玩轉雲端開發 7 天訓練營
提前享受雲時代的原生開發環境,Serverless 研發從入門到精通,連續 7 天,每天一個直播,阿里專家手把手教你利用阿里云云開發平臺 get 雲端開發新技能。0 門檻打開瀏覽器就可以開發,最快 1 分鐘搭建個人網站,免費開發還送代金券、天貓精靈等多重好禮!
識別下方二維碼馬上入群學習,或點擊鏈接馬上參加:
等等,福利還沒停!關注下方公眾號轉發文章即參與抽取天貓精靈!
關注「Alibaba F2E」
把握阿里巴巴前端新動向