進(jìn)擊的 JAMStack

作者簡(jiǎn)介:
李中凱
八年多工作經(jīng)驗(yàn) 前端負(fù)責(zé)人,
擅長(zhǎng)JavaScript/Vue。
掘金文章專欄:https://juejin.im/user/57c7cb8a0a2b58006b1b8666/posts
公眾號(hào):1024譯站

什么是JAMStack

概念

JAMStack中的JAM其實(shí)是三個(gè)詞的縮寫,它們分別是JavaScript, APIs以及Markdown。而Stack用中文的說法就是技術(shù)棧(Tech Stack),也就是我們?cè)跇?gòu)建應(yīng)用的時(shí)候具體使用到的技術(shù)的集合。舉個(gè)例子,國(guó)外現(xiàn)在比較火的一個(gè)Stack叫做Mean Stack,它表示使用MongoDB + Express.js + AngularJS + Node.js這些技術(shù)來構(gòu)建一個(gè)Web應(yīng)用。因此用最通俗易懂的話來描述JAMStack就是:使用JavaScript,APIs和Markdown三種技術(shù)來構(gòu)建Web應(yīng)用。所以JAMStack是一種問題解決方案,而不是一個(gè)具體的實(shí)現(xiàn)。

接著我們?cè)倬唧w看一下JavaScript,APIs和Markdown這三種技術(shù)在JAMStack的世界中是起到什么作用的。

JavaScript

在JAMStack的概念中,JavaScript指的是在客戶端(client)實(shí)現(xiàn)動(dòng)態(tài)網(wǎng)頁(yè)效果的JavaScript,它既可以是React和Vue這種Web框架,也可以是原生的JavaScript。它主要負(fù)責(zé)網(wǎng)頁(yè)動(dòng)態(tài)的內(nèi)容。

APIs

這里的API和我們平時(shí)開發(fā)調(diào)用的API是一樣的。JAMStack的Web應(yīng)用會(huì)通過JavaScript給后端API發(fā)送AJAX請(qǐng)求或者GraphQL query,后端API會(huì)以某種格式(一般是JSON)返回?cái)?shù)據(jù)給前端來實(shí)現(xiàn)一些用戶交互。

Markdown

Mardown是一種輕量級(jí)的標(biāo)記語(yǔ)言。在JAMStack的世界中,Markdown類型的文件通常是用來作為生成靜態(tài)HTML文件的數(shù)據(jù)源。有用過hexo寫博客的同學(xué)對(duì)這個(gè)概念肯定不會(huì)陌生,因?yàn)閔exo的原理就是將我們編寫的Markdown文件根據(jù)我們指定的主題或者模板生成一些靜態(tài)的HTML然后托管在github pages或者其它類似的靜態(tài)網(wǎng)站服務(wù)器來供別人訪問的。

除了Markdown文件之外,JAMStack的靜態(tài)數(shù)據(jù)源還可以是其它的東西,例如我們后面說到的Gatsby(JAMStack的一種實(shí)現(xiàn))就允許通過插件的方式使用SQL直接讀取數(shù)據(jù)庫(kù)的內(nèi)容來生成靜態(tài)頁(yè)面。

了解了這三個(gè)概念的具體內(nèi)容后,我們?cè)偻ㄟ^一個(gè)Gatsby的小demo來體會(huì)一下JAMStack的應(yīng)用是如何工作的。

Gatsby Demo

由于文章篇幅的限制,我將不在這里為大家講述Gatsby的具體用法,不過我后面會(huì)寫一系列文章來教大家如何用Gatsby來免費(fèi)構(gòu)建一個(gè)比較大的內(nèi)容網(wǎng)站(CMS),大家可以留意一下。

簡(jiǎn)單來說,Gatsby是一個(gè)可以讓開發(fā)者使用React,GraphQL等現(xiàn)代技術(shù)快速開發(fā)網(wǎng)站的靜態(tài)網(wǎng)站生成器(static-site generator)。它是存在于網(wǎng)站構(gòu)建(build)階段的一個(gè)工具。為了給大家一個(gè)直觀點(diǎn)的認(rèn)識(shí),我使用Gatsby搭建了一個(gè)簡(jiǎn)單的個(gè)人博客網(wǎng)站,網(wǎng)站的源代碼可以在我的github倉(cāng)庫(kù)找到。

博客網(wǎng)站包含以下的功能:

  • 博客列表頁(yè)面:展示我發(fā)表的所有博客。(靜態(tài)內(nèi)容)

  • 博客詳情頁(yè)面:展示每一篇博客的具體內(nèi)容。(靜態(tài)內(nèi)容)

  • 博客評(píng)論列表:游客評(píng)論博客以及展示游客對(duì)這篇博客的評(píng)論列表。(動(dòng)態(tài)內(nèi)容)

細(xì)心的你一定注意到了我在上面每個(gè)功能點(diǎn)的右邊標(biāo)出了這個(gè)功能是靜態(tài)的還是動(dòng)態(tài)的。所謂靜態(tài)的內(nèi)容就是那些不會(huì)經(jīng)常發(fā)生變化的內(nèi)容,這些內(nèi)容在一段時(shí)間內(nèi)不同用戶訪問的時(shí)候都會(huì)得到同樣的結(jié)果。而動(dòng)態(tài)的內(nèi)容就是那些頻繁發(fā)生變化的內(nèi)容,例如游客對(duì)我的博客的評(píng)論。那么我為什么要區(qū)分開這兩種類型的內(nèi)容呢?要回答這個(gè)問題我們可以先看看如果使用服務(wù)端渲染(SSR)的方案這個(gè)博客應(yīng)用是如何運(yùn)行的。首先游客會(huì)向SSR服務(wù)器發(fā)送一個(gè)查看某個(gè)博客的請(qǐng)求,SSR服務(wù)器收到請(qǐng)求后向后端服務(wù)請(qǐng)求這個(gè)博客的內(nèi)容然后渲染出一個(gè)HTML頁(yè)面然后返回給用戶。這時(shí)候如果其他用戶也向SSR服務(wù)器請(qǐng)求了同樣的資源,SSR服務(wù)器還是會(huì)做同樣的工作,請(qǐng)求資源 + 渲染頁(yè)面。這個(gè)時(shí)候其實(shí)SSR服務(wù)器消耗了很多IO和CPU資源來做這些重復(fù)性的渲染,而且隨著你的博客訪問量的增大這些無用的資源消耗也會(huì)越來越多,在不升級(jí)服務(wù)端資源的前提下用戶體驗(yàn)也會(huì)隨之變差。到這里你可能會(huì)問,既然服務(wù)端渲染這么浪費(fèi)資源,我們不進(jìn)行SSR,直接將webpack打包生成的文件放在一個(gè)靜態(tài)服務(wù)器然后頁(yè)面都是在瀏覽器渲染不就行了嗎?從實(shí)現(xiàn)博客功能的層面上來說這是沒有問題的,可是這對(duì)搜索引擎優(yōu)化(SEO)很不友好,百度收錄不了你的博客,你的網(wǎng)站火不起來?。?/p>

為了避免重復(fù)性的無用渲染而且能對(duì)SEO友好,Gatsby采取了區(qū)分網(wǎng)站靜態(tài)內(nèi)容和動(dòng)態(tài)內(nèi)容的技術(shù)方案。對(duì)于那些不經(jīng)常變動(dòng)的而且希望被搜索引擎收錄的靜態(tài)內(nèi)容,Gatsby會(huì)在Webpack打包階段就生成,這樣就不需要在用戶訪問該頁(yè)面的時(shí)候才浪費(fèi)資源來渲染頁(yè)面了,而且這些靜態(tài)文件還可以通過CDN來優(yōu)化用戶體驗(yàn)。而對(duì)于那些數(shù)據(jù)經(jīng)常發(fā)生變化的且不需要被搜索引擎收錄的內(nèi)容,它們會(huì)等到瀏覽器實(shí)際渲染對(duì)應(yīng)組件的時(shí)候才通過APIs動(dòng)態(tài)獲取數(shù)據(jù)渲染出來。

我們接著來看一下博客網(wǎng)站的代碼目錄結(jié)構(gòu):

image

上面代碼中,server文件夾存放的是一個(gè)簡(jiǎn)單的管理用戶評(píng)論的express應(yīng)用,src文件夾才是Gatsby操作的前端資源,它包括以下內(nèi)容:

  • blogs:這個(gè)文件夾是用來存放博客內(nèi)容的,每一個(gè)Markdown文件都會(huì)生成一個(gè)靜態(tài)的HTML文件。

  • components: 存放React組件用的。

  • images:存放博客的一些圖片資源。

  • pages: 網(wǎng)站的路由文件夾,這個(gè)文件夾下的每一個(gè)文件都會(huì)被生成一個(gè)對(duì)應(yīng)的HTML靜態(tài)文件,當(dāng)請(qǐng)求該路由時(shí)會(huì)直接返回該靜態(tài)文件。例如現(xiàn)在pages底下有兩個(gè)路由,404的路由對(duì)應(yīng)著的是沒找到資源的頁(yè)面,而index路由則是博客的主頁(yè)面。

  • templates: 網(wǎng)站的模板文件夾,該文件夾底下只有一個(gè)叫做blog-post.js的模板文件,在Gatsby構(gòu)建網(wǎng)站的時(shí)候blogs文件夾底下的每一個(gè)Markdown文件都會(huì)通過這個(gè)模板文件生成一個(gè)對(duì)應(yīng)的HTML文件,這樣當(dāng)用戶訪問服務(wù)器的時(shí)候博客的HTML文件就會(huì)被直接返回而無需進(jìn)行服務(wù)端渲染了。

接著我們可以看一下Gatsby打包會(huì)生成哪些文件:

image

由上圖可以看出,Gatsby會(huì)為每一個(gè)pages文件夾底下的文件生成一個(gè)對(duì)應(yīng)的html文件,以及為每一個(gè)blogs文件夾底下的博客生成一個(gè)靜態(tài)的HTML文件,同時(shí)還有一些在客戶端執(zhí)行的JS文件。生成的文件可以直接使用靜態(tài)網(wǎng)站服務(wù)器來為用戶提供服務(wù),同時(shí)你還可以把它們放在CDN中來讓用戶訪問起來更快。

最后讓我們來看一下這個(gè)博客網(wǎng)站的運(yùn)行效果吧:

image

上圖中我點(diǎn)擊了“如何馬上實(shí)現(xiàn)財(cái)富自由”這個(gè)博客,進(jìn)入到博客詳情頁(yè)時(shí)瀏覽器沒有重新向服務(wù)端請(qǐng)求博客詳情的HTML文件,而是直接在瀏覽器完成渲染,用戶體驗(yàn)非常之流暢。這其實(shí)是Gatsby應(yīng)用的一個(gè)很大的亮點(diǎn),那就是:Gatsby打包的應(yīng)用在瀏覽器首次請(qǐng)求獲得提前生成的靜態(tài)HTML文件后,會(huì)演變成一個(gè)React SPA應(yīng)用,接下來的用戶交互就和一般的SPA應(yīng)用沒有任何差別了,換句話來說,Gatsby既保留了SSR方案SEO友好的優(yōu)點(diǎn)又保留了SPA應(yīng)用的流暢用戶體驗(yàn),可謂是各取所長(zhǎng),揚(yáng)長(zhǎng)補(bǔ)短了!

其他例子

其實(shí)JAMStack的應(yīng)用現(xiàn)在已經(jīng)有很多了,只不過我們平時(shí)沒有留意到而已。舉個(gè)例子,React開發(fā)者十分熟悉的React官網(wǎng)reactjs.org就是用Gatsby構(gòu)建。那么除了這些比較簡(jiǎn)單的文檔性和博客網(wǎng)站,JAMStack可以用來構(gòu)建復(fù)雜的商業(yè)應(yīng)用嗎?答案是肯定的,除了一些簡(jiǎn)單的CMS平臺(tái),JAMStack還可以用來搭建諸如braun這類電商平臺(tái),你可能想不到的是著名的程序員學(xué)習(xí)網(wǎng)站freeCodeCamp也是使用JAMStack技術(shù)棧來搭建的,大家可以去網(wǎng)上(Google)查一下關(guān)于freeCodeCamp架構(gòu)設(shè)計(jì)的視頻或文章,看完之后我相信你會(huì)對(duì)JAMStack有更深入的理解的。

JAMStack的優(yōu)勢(shì)

在上面的介紹中我已經(jīng)大概說了一些JAMStack的優(yōu)勢(shì)了,其中包括SEO友好還有流暢的用戶體驗(yàn),那么除了這些,JAMStack還有沒有其它吸引人的地方呢?

高性能

為什么JAMStack是高性能的呢?這是因?yàn)镴AMStack的應(yīng)用將網(wǎng)站的靜態(tài)部分和動(dòng)態(tài)部分區(qū)分開來了,那些不會(huì)頻繁發(fā)生變化的內(nèi)容會(huì)被提前生成,從而無需使用額外的計(jì)算資源來進(jìn)行服務(wù)端渲染。這樣用戶首次訪問某個(gè)頁(yè)面的時(shí)候速度會(huì)變得很快,而且這些靜態(tài)的資源還可以被放在CDN來進(jìn)一步提升用戶體驗(yàn)。將動(dòng)態(tài)內(nèi)容和靜態(tài)內(nèi)容區(qū)分開來還有另外一個(gè)好處,就是我們后端接口的職責(zé)更加明確了,API接口的數(shù)量會(huì)變得更少,性能也會(huì)變得更好。

高性價(jià)比以及高可擴(kuò)展性

由于我們前端的內(nèi)容都是一些靜態(tài)的文件沒有服務(wù)端渲染的要求,而靜態(tài)資源服務(wù)器對(duì)性能的要求并不高,所以我們?cè)谫?gòu)買服務(wù)器方面不需要很大的成本,我們甚至還可以使用一些諸如netlify和Gatsby Cloud等免費(fèi)資源來托管我們的文件。對(duì)于后端來說由于我們已經(jīng)將前后端徹底分離了,所以后端可以使用一些廉價(jià)的Baas或者Serverless服務(wù),例如可以使用Auth0作為我們的用戶鑒權(quán)服務(wù),使用Firebase作為我們的接口服務(wù)等等。使用這些Baas和Serverless服務(wù)有一個(gè)好處就是它們很便宜,而且它們是按照接口使用量來收費(fèi)的,你的用戶量決定了你的支出,如果你的用戶很少,你甚至不需要花一分錢。

除了極高的性價(jià)比,JAMStack還有很好的擴(kuò)展性。舉個(gè)例子,假如你現(xiàn)在的博客網(wǎng)站因?yàn)槟骋黄┛屯蝗换鹆?,訪問用戶激增。如果你的前端靜態(tài)文件使用的是CDN網(wǎng)絡(luò)的話,你的網(wǎng)站很容易就可以擴(kuò)展了,一切都是自動(dòng)的,無需你做任何東西,而后端如果你使用了Serverless和Baas的解決方案的話,一切也是自動(dòng)的,用戶不會(huì)感覺到有使用體驗(yàn)的差別,而你只需要給使用到的服務(wù)平臺(tái)多一點(diǎn)點(diǎn)費(fèi)用而已。

更好的開發(fā)者體驗(yàn)

拿我們前面提到的Gatsby來舉例,它就允許我們使用一些現(xiàn)代的前端技術(shù)來進(jìn)行開發(fā),例如React,Styled-components和GraphQL等,這些都是我們前端開發(fā)者十分熟悉的技術(shù)了,沒有很大的學(xué)習(xí)成本所以開發(fā)者體驗(yàn)會(huì)很好。除此之外,由于Gatsby使用了React,所以它間接上接入了React的生態(tài)系統(tǒng),這樣開發(fā)者在開發(fā)Gatsby應(yīng)用時(shí)就可以使用React生態(tài)的各種最佳實(shí)踐和庫(kù)實(shí)現(xiàn)了,這無疑可以大大提高我們的開發(fā)效率。

更高的安全性

由于JAMStack是一種前后端分離的技術(shù),沒有了后端渲染所以可以降低被攻擊的風(fēng)險(xiǎn)。舉個(gè)例子采用Gatsby生成的CMS平臺(tái)就比傳統(tǒng)的WordPress平臺(tái)安全很多:)。

JAMStack適合什么應(yīng)用

既然JAMStack有那么多好處,我們是不是一把梭在所有的項(xiàng)目中都使用JAMStack呢?答案是否定的,由于JAMStack需要我們將網(wǎng)站的靜態(tài)部分和動(dòng)態(tài)部分區(qū)分開來,靜態(tài)部分的內(nèi)容會(huì)在構(gòu)建的時(shí)候就生成而動(dòng)態(tài)的內(nèi)容會(huì)在瀏覽器進(jìn)行渲染,這個(gè)特點(diǎn)就注定了它不適合于構(gòu)建以下類型的應(yīng)用:

  • 掘金,知乎這種主要由第三方用戶創(chuàng)建內(nèi)容的應(yīng)用。由于這些應(yīng)用的內(nèi)容都是由平臺(tái)用戶創(chuàng)建的,而且用戶可以不斷地修改和刪除已經(jīng)創(chuàng)建的內(nèi)容,如果使用JAMStack的話網(wǎng)站的內(nèi)容就需要被頻繁構(gòu)建,這顯然是不合理的。

  • 微博,推特這種社交應(yīng)用。這類應(yīng)用的內(nèi)容除了頻繁更新之外,還有就是動(dòng)態(tài)內(nèi)容多于靜態(tài)內(nèi)容,例如用戶的主頁(yè)只會(huì)展示他關(guān)注的人發(fā)表的動(dòng)態(tài),所以也不適合使用JAMStack。

  • 一些不需要SEO的應(yīng)用。JAMStack一個(gè)很大的優(yōu)點(diǎn)就是對(duì)SEO友好,如果你的應(yīng)用沒有被搜索引擎收錄的需求的話,就沒必要使用JAMStack了。

  • 內(nèi)容很多的應(yīng)用。由于JAMStack需要我們每次都構(gòu)建出所有的靜態(tài)資源,所以對(duì)于那些靜態(tài)內(nèi)容很多的應(yīng)用(例如頁(yè)面數(shù)超過50k)的話,每次構(gòu)建應(yīng)用都需要大量的時(shí)間,因此這種類型的網(wǎng)站也不適合用JAMStack。

相反JAMStack十分適合構(gòu)建以下類型的應(yīng)用:

  • 項(xiàng)目文檔之類的網(wǎng)站,例如React的官網(wǎng)等。

  • 企業(yè)或者組織的官方網(wǎng)站。

  • 個(gè)人管理的博客網(wǎng)站。

  • 中小型規(guī)模的CMS平臺(tái)。

  • 中小型的電商平臺(tái)。

  • 既有需要被SEO的靜態(tài)內(nèi)容又有動(dòng)態(tài)的不需要SEO的內(nèi)容的混合應(yīng)用。例如一些To B的平臺(tái),里面既有用戶的工作臺(tái)又有一些操作文檔相關(guān)的靜態(tài)內(nèi)容。

當(dāng)然了我在這里列出來的無論是適用還是不適用JAMStack的應(yīng)用其實(shí)都是一些很籠統(tǒng)的分類,我們?cè)趯?shí)際開發(fā)時(shí)還得具體問題具體分析,根據(jù)實(shí)際情況來評(píng)估我們的應(yīng)用是不是適合使用JAMStack來開發(fā)。

我的個(gè)人思考

在最后我想說一下我自己對(duì)JAMStack的一些思考。

首先我個(gè)人十分看好這個(gè)技術(shù)棧,也會(huì)在日后的開發(fā)中使用這個(gè)技術(shù)棧。因?yàn)樗鼛臀医鉀Q了網(wǎng)站SEO的問題。在不了解JAMStack之前,如果我想我的網(wǎng)站被搜索引擎收錄要么就是刀耕火種地硬寫HTML和原生JS,這種方案明顯開發(fā)效率十分低下。還有一種方案就是我使用React等現(xiàn)代開發(fā)技術(shù),這樣我就得學(xué)習(xí)next.js等SSR技術(shù)來實(shí)現(xiàn)SEO,這個(gè)方案有一個(gè)問題就是學(xué)習(xí)next.js有一定的學(xué)習(xí)成本,而且在項(xiàng)目上線后我得維護(hù)一個(gè)后端服務(wù)來進(jìn)行服務(wù)端渲染,所以會(huì)有一定的運(yùn)維成本。可是使用了JAMStack或者說是Gatsby后這些問題就迎刃而解了,因?yàn)槲铱梢岳^續(xù)使用我熟悉的React技術(shù)棧來快速開發(fā)Web應(yīng)用,還無需考慮服務(wù)端渲染的問題就可以達(dá)到SEO的效果,這不是美滋滋?

其次我覺得JAMStack這個(gè)技術(shù)棧十分有利于我們實(shí)踐一些自己想到的不確定能不能成功的點(diǎn)子(創(chuàng)業(yè)想法)。上面在介紹JAMStack優(yōu)勢(shì)的時(shí)候,我提到了一點(diǎn)就是使用JAMStack其實(shí)你可以免費(fèi)部署你的應(yīng)用,因?yàn)槟憧梢詫⑶岸说撵o態(tài)代碼放在一些免費(fèi)的靜態(tài)資源托管服務(wù)器,然后后端使用一些免費(fèi)的Baas API服務(wù),當(dāng)然了這只適合于我們平臺(tái)用戶量不大的情景,當(dāng)用戶量大的時(shí)候我們還是得付費(fèi)的。可是我們網(wǎng)站剛起步的時(shí)候用戶量不都是不大的嗎?如果我們一大早就買好服務(wù)器資源和域名,后面卻發(fā)現(xiàn)這個(gè)想法根本行不通的話,這些錢就算是賠進(jìn)去了。相反,使用免費(fèi)服務(wù)的話,即使我們做的東西黃了,我們也不會(huì)有什么損失。

總的來說我對(duì)JAMStack這個(gè)技術(shù)棧是很有信心的,特別是在CMS內(nèi)容管理平臺(tái)這方面我相信它一定會(huì)逐漸火起來,而且有可能可以取代WordPress的地位。

作者簡(jiǎn)介:
李中凱
八年多工作經(jīng)驗(yàn) 前端負(fù)責(zé)人,
擅長(zhǎng)JavaScript/Vue。
掘金文章專欄:https://juejin.im/user/57c7cb8a0a2b58006b1b8666/posts
公眾號(hào):1024譯站

本文已經(jīng)獲得李中凱老師授權(quán)轉(zhuǎn)發(fā),其他人若有興趣轉(zhuǎn)載,請(qǐng)直接聯(lián)系作者授權(quán)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容