如果您認為靜態(tài)呈現(xiàn)僅限于對網(wǎng)站的每個用戶都一樣的通用公共內(nèi)容,那么您絕對應(yīng)該閱讀這篇文章。
分段呈現(xiàn)(Segmented Rendering)是Jamstack的一種新模式,它允許您靜態(tài)地個性化內(nèi)容,而不需要任何類型的客戶端呈現(xiàn)或基于請求的服務(wù)器端呈現(xiàn)。有許多用例:個性化、國際化、主題化、多租戶、A/B測試…
讓我們關(guān)注一個對博客所有者非常有用的場景:處理付費內(nèi)容。
祝賀你找到了新工作#
哇,你剛剛升職了!你現(xiàn)在是《修補》雜志的“表演主管”,這是《粉碎》雜志最大的競爭對手。修復(fù)雜志有一個非常奇特的商業(yè)模式。每篇文章中的詼諧段子只有付費用戶才能看到。
程序員為什么要過馬路?
我打賭你會付錢知道答案。
您今天的任務(wù)是以最佳性能實現(xiàn)這一特性。讓我們看看你怎么做。提示:我們將引入一個名為“分段渲染”的新模式
使用現(xiàn)代Javascript框架呈現(xiàn)網(wǎng)頁的多種方式#
Next.js的流行源于其對“渲染三力”的掌握,即在一個框架中結(jié)合客戶端渲染、基于請求的服務(wù)器渲染和靜態(tài)渲染的能力。
南車,SSR,SSG…讓我們澄清一下他們是什么#
修復(fù)雜志用戶界面依賴于一個現(xiàn)代的Javascript庫,React。像其他類似的UI庫一樣,React提供了兩種呈現(xiàn)內(nèi)容的方式:客戶端和服務(wù)器端。
客戶端渲染(CSR)發(fā)生在用戶的瀏覽器中。在過去,我們會使用jQuery來完成CSR。
服務(wù)器端呈現(xiàn)發(fā)生在您自己的服務(wù)器上,要么在請求時(SSR),要么在構(gòu)建時(靜態(tài)或SSG)。SSR和SSG也存在于Javascript生態(tài)系統(tǒng)之外。例如,想想PHP或Jekyll。
讓我們看看這些模式如何應(yīng)用到我們的用例中。
CSR:丑陋的裝載機問題#
客戶端渲染(CSR)會在頁面加載后在瀏覽器中使用Javascript來添加詼諧的笑話。我們可以使用“fetch”來獲取笑話內(nèi)容,然后將它們插入DOM。
CSR涉及冗余的客戶端計算和大量難看的加載器。
這是可行的,但這是最好的方法嗎?你的服務(wù)員必須為每個讀者提供詼諧的笑話。如果有任何事情導(dǎo)致Javascript代碼失敗,付費用戶將不會得到他們想要的樂趣,可能會生氣。如果用戶有一個緩慢的網(wǎng)絡(luò)或緩慢的計算機,當他們的笑話被下載時,他們會看到一個丑陋的加載程序。請記住,大多數(shù)訪問者是通過移動設(shè)備瀏覽的!
隨著API調(diào)用數(shù)量的增加,這個問題只會變得更糟。請記住,一個瀏覽器只能并行運行少量請求(通常每個服務(wù)器/代理6個請求)。服務(wù)器端呈現(xiàn)不受此限制,并且在從您自己的內(nèi)部服務(wù)獲取數(shù)據(jù)時會更快。
每個請求的SSR:被第一個字節(jié)占用#
每請求服務(wù)器端呈現(xiàn)(SSR)在服務(wù)器上按需生成內(nèi)容。如果用戶付費,服務(wù)器直接以HTML的形式返回整篇文章。否則,它會返回沒有任何樂趣的乏味文章。
SSR移除了客戶端計算,但沒有移除加載時間。
我們不再依賴客戶端Javascript。然而,為每個請求呈現(xiàn)文章并不節(jié)能。到達第一個字節(jié)的時間(TTFB)也增加了,因為在我們開始看到一些內(nèi)容之前,我們必須等待服務(wù)器完成它的工作。
我們已經(jīng)用更難看的空白屏幕取代了難看的客戶端加載程序!現(xiàn)在我們還要為此付出代價!
“重新驗證時失效”緩存控制策略可以通過在頁面更新前提供緩存版本來減少TTFB問題。但對于個性化內(nèi)容,它不能開箱即用,因為在不考慮cookies的情況下,它只能緩存每個URL的一個頁面版本,并且不能處理提供付費內(nèi)容所需的安全檢查。
靜態(tài)渲染:富客戶/窮客戶問題的關(guān)鍵#
在這一點上,你碰到了我稱之為“富客戶/窮客戶”的問題:你的高級用戶得到的是最差的性能,而不是最好的。
根據(jù)設(shè)計,與靜態(tài)呈現(xiàn)相比,客戶端呈現(xiàn)和每請求服務(wù)器端呈現(xiàn)涉及最多的計算,靜態(tài)呈現(xiàn)在構(gòu)建時只發(fā)生一次。
我所知道的99%的網(wǎng)站都會選擇CSR或者SSR,并且飽受博客/窮客戶問題的困擾。
深入了解分段渲染#
分段渲染只是進行靜態(tài)渲染的一種更聰明的方式。一旦你理解了這一切都是關(guān)于緩存渲染,然后為每個請求獲得正確的緩存渲染,一切都會水到渠成。
靜態(tài)渲染提供了最佳性能,但靈活性較差#
靜態(tài)站點生成(SSG)在構(gòu)建時生成內(nèi)容。這是性能最好的方法,因為我們一次性地呈現(xiàn)了文章。然后作為純HTML提供。
這解釋了為什么構(gòu)建時預(yù)渲染是Jamstack理念的基石之一。作為新晉升的“業(yè)績負責(zé)人”,這絕對是你想要的!
截至2022年,所有Jamstack框架都有大致相同的靜態(tài)渲染方法:
- 你計算所有可能的URL的列表;
- 您為每個URL呈現(xiàn)一個頁面。
靜態(tài)渲染第一步的結(jié)果:計算一堆你要預(yù)渲染的URL。對于博客來說,它通常是你所有文章的列表。在第2步中,您只需呈現(xiàn)每篇文章,每個URL一篇。
這意味著一個URL嚴格地等于頁面的一個版本。你不能在同一個網(wǎng)址上有一篇文章的付費和免費版本,即使是對不同的用戶。網(wǎng)址/如何修理一個壞掉的雜志將向每個人提供相同的HTML內(nèi)容,沒有任何個性化選項。不可能考慮請求cookies。
分段呈現(xiàn)可以更進一步,為同一URL呈現(xiàn)不同的變化。讓我們學(xué)習(xí)如何。
解耦URL和頁面變化#
允許個性化內(nèi)容的最天真的解決方案是給URL添加一個新的路由參數(shù),例如,“有笑話”對“平淡無奇”
Next.js的實現(xiàn)大致如下:
第一個函數(shù)為同一篇文章計算2個URL,一個有趣的和一個乏味的。第二個函數(shù)得到了笑話,但只針對付費版本。
太好了,你的文章有兩個版本。我們可以開始在“分段渲染”中看到“分段”——付費用戶和免費用戶,每個分段有一個渲染版本。
但是現(xiàn)在,你有了一個新的問題:如何將用戶重定向到正確的頁面?簡單:直接將用戶重定向到正確的頁面!有服務(wù)器什么的!
起初,您需要一個web服務(wù)器來實現(xiàn)高效的靜態(tài)渲染,這聽起來可能很奇怪。但是請相信我:靜態(tài)網(wǎng)站獲得最佳性能的唯一方法是做一些服務(wù)器優(yōu)化
使用免費的axe DevTools Chrome瀏覽器擴展,只需幾分鐘即可開始可訪問性測試。
關(guān)于“靜態(tài)”主機的說明#
如果你來自Jamstack生態(tài)系統(tǒng),你可能會愛上靜態(tài)托管。有什么感覺比推送幾個文件,讓你的網(wǎng)站在GitHub頁面上啟動運行更好呢?還是直接在內(nèi)容交付網(wǎng)絡(luò)(CDN)上托管成熟的應(yīng)用程序?
然而“靜態(tài)托管”并不意味著沒有服務(wù)器。這意味著你不能控制服務(wù)器。仍然有一個服務(wù)器負責(zé)將每個URL指向正確的靜態(tài)文件。
靜態(tài)托管應(yīng)該被看作是一個有限的,但廉價和高性能的選擇,以托管個人網(wǎng)站或公司登錄頁面。如果您想超越這一點,您將需要控制服務(wù)器,至少要處理諸如基于請求cookies或頭的重定向之類的事情。
雖然不需要打電話給后端專家。我們不需要任何復(fù)雜的計算??梢詸z查用戶是否付費的非常基本的重定向服務(wù)器就可以了。
好消息:Vercel或Netlify等現(xiàn)代主機實現(xiàn)了邊緣處理程序,這正是我們這里需要的。Next.js將這些邊緣處理程序?qū)崿F(xiàn)為“中間件”,因此您可以用Javascript對它們進行編碼。
“邊緣”意味著計算盡可能靠近最終用戶,而不是擁有幾個大型集中式服務(wù)器。您可以將它們視為核心基礎(chǔ)架構(gòu)的外墻。它們非常適合個性化,這通常與用戶的實際地理位置有關(guān)。
使用NEXT.JS中間件輕松重定向#
Next.js中間件非???,編碼非常簡單。與AWS Gateway等云代理或Nginx等開源工具不同,中間件是用Javascript編寫的,使用Web標準,即獲取API。
在“分段呈現(xiàn)”架構(gòu)中,中間件只是負責(zé)將每個用戶請求指向頁面的正確版本:
進口 {NextResponse} 從 "下一個/服務(wù)器"; 進口類型{下一個請求} 從 "下一個/服務(wù)器"; 異步?非同步(asynchronous) 功能 中間件(請求:下一個請求) { // isPaidFromReq可以讀取cookies,獲取身份驗證令牌, //并驗證用戶是否確實是付費會員 常數(shù)isPaid= 等待 isPaidFromReq(請求); 常數(shù)例行程序=isPaid? “帶-笑話” : “淡而無味”; 返回NextResponse。再直接的( `/${例行程序}/如何修理一個壞掉的雜志` ); }
一個為付費和免費用戶實現(xiàn)分段渲染的中間件。
嗯,就是這樣。你作為“表演主管”的第一天結(jié)束了。你擁有一切你需要的東西來為你怪異的商業(yè)模式實現(xiàn)最好的表現(xiàn)!
當然,您可以將這種模式應(yīng)用于許多其他用例:國際化內(nèi)容、A/B測試、亮/暗模式、個性化……您的頁面的每一種變化都構(gòu)成了一個新的“部分”:法國用戶、喜歡暗主題的人或付費用戶。
頂端的櫻桃:URL重寫#
但是,嘿,你是“性能的頭”,而不是“性能的平均”!你希望你的web應(yīng)用程序是完美的,而不僅僅是好的!你的網(wǎng)站在所有指標上都非???,但現(xiàn)在你的文章網(wǎng)址看起來像這樣:
那真的不好看…分段渲染很棒,但是最終用戶不需要知道它自己的“分段”對優(yōu)秀工作的懲罰是更多的工作,所以讓我們添加最后一點:不要使用URL重定向,使用URL重寫。它們是完全一樣的東西,除了你不會在URL中看到參數(shù)。
網(wǎng)址/如何縮短網(wǎng)址沒有任何路由參數(shù),現(xiàn)在將根據(jù)用戶的cookies顯示頁面的正確版本。route參數(shù)仍然“存在”在您的應(yīng)用程序中,但是最終用戶看不到它,并且URL保持干凈。完美。