最近在研究JAMStack的一些相关内容,发现这的确是个好东西,所以想写一篇文章把这个概念分享给还不了解JAMStack的同学。本篇文章主要包含以下的内容:
JAMStack中的JAM其实是三个词的缩写,它们分别是JavaScript, APIs以及Markdown。而Stack用中文的说法就是技术栈(Tech Stack),也就是我们在构建应用的时候具体使用到的技术的集合。举个例子,国外现在比较火的一个Stack叫做Mean Stack,它表示使用MongoDB + Express.js + AngularJS + Node.js这些技术来构建一个Web应用。因此用最通俗易懂的话来描述JAMStack就是:使用JavaScript,APIs和Markdown三种技术来构建Web应用。所以JAMStack是一种问题解决方案,而不是一个具体的实现。
接着我们再具体看一下JavaScript,APIs和Markdown这三种技术在JAMStack的世界中是起到什么作用的。
在JAMStack的概念中,JavaScript指的是在客户端(client)实现动态网页效果的JavaScript,它既可以是React和Vue这种Web框架,也可以是原生的JavaScript。它主要负责网页动态的内容。
这里的API和我们平时开发调用的API是一样的。JAMStack的Web应用会通过JavaScript给后端API发送AJAX请求或者GraphQL query,后端API会以某种格式(一般是JSON)返回数据给前端来实现一些用户交互。
Mardown是一种轻量级的标记语言。在JAMStack的世界中,Markdown类型的文件通常是用来作为生成静态HTML文件的数据源。有用过hexo写博客的同学对这个概念肯定不会陌生,因为hexo的原理就是将我们编写的Markdown文件根据我们指定的主题或者模板生成一些静态的HTML然后托管在github pages或者其它类似的静态网站服务器来供别人访问的。
除了Markdown文件之外,JAMStack的静态数据源还可以是其它的东西,例如我们后面说到的Gatsby(JAMStack的一种实现)就允许通过插件的方式使用SQL直接读取数据库的内容来生成静态页面。
了解了这三个概念的具体内容后,我们再通过一个Gatsby的小demo来体会一下JAMStack的应用是如何工作的。
由于文章篇幅的限制,我将不在这里为大家讲述Gatsby的具体用法,不过我后面会写一系列文章来教大家如何用Gatsby来免费构建一个比较大的内容网站(CMS),大家可以留意一下。
简单来说,Gatsby是一个可以让开发者使用React,GraphQL等现代技术快速开发网站的静态网站生成器(static-site generator)。它是存在于网站构建(build)阶段的一个工具。为了给大家一个直观点的认识,我使用Gatsby搭建了一个简单的个人博客网站,网站的源代码可以在我的github仓库找到。
博客网站包含以下的功能:
细心的你一定注意到了我在上面每个功能点的右边标出了这个功能是静态的还是动态的。所谓静态的内容就是那些不会经常发生变化的内容,这些内容在一段时间内不同用户访问的时候都会得到同样的结果。而动态的内容就是那些频繁发生变化的内容,例如游客对我的博客的评论。那么我为什么要区分开这两种类型的内容呢?要回答这个问题我们可以先看看如果使用服务端渲染(SSR)的方案这个博客应用是如何运行的。首先游客会向SSR服务器发送一个查看某个博客的请求,SSR服务器收到请求后向后端服务请求这个博客的内容然后渲染出一个HTML页面然后返回给用户。这时候如果其他用户也向SSR服务器请求了同样的资源,SSR服务器还是会做同样的工作,请求资源 + 渲染页面。这个时候其实SSR服务器消耗了很多IO和CPU资源来做这些重复性的渲染,而且随着你的博客访问量的增大这些无用的资源消耗也会越来越多,在不升级服务端资源的前提下用户体验也会随之变差。到这里你可能会问,既然服务端渲染这么浪费资源,我们不进行SSR,直接将webpack打包生成的文件放在一个静态服务器然后页面都是在浏览器渲染不就行了吗?从实现博客功能的层面上来说这是没有问题的,可是这对搜索引擎优化(SEO)很不友好,百度收录不了你的博客,你的网站火不起来啊!
为了避免重复性的无用渲染而且能对SEO友好,Gatsby采取了区分网站静态内容和动态内容的技术方案。对于那些不经常变动的而且希望被搜索引擎收录的静态内容,Gatsby会在Webpack打包阶段就生成,这样就不需要在用户访问该页面的时候才浪费资源来渲染页面了,而且这些静态文件还可以通过CDN来优化用户体验。而对于那些数据经常发生变化的且不需要被搜索引擎收录的内容,它们会等到浏览器实际渲染对应组件的时候才通过APIs动态获取数据渲染出来。
我们接着来看一下博客网站的代码目录结构:
上面代码中,server文件夹存放的是一个简单的管理用户评论的express应用,src文件夹才是Gatsby操作的前端资源,它包括以下内容:
接着我们可以看一下Gatsby打包会生成哪些文件:
由上图可以看出,Gatsby会为每一个pages文件夹底下的文件生成一个对应的html文件,以及为每一个blogs文件夹底下的博客生成一个静态的HTML文件,同时还有一些在客户端执行的JS文件。生成的文件可以直接使用静态网站服务器来为用户提供服务,同时你还可以把它们放在CDN中来让用户访问起来更快。
最后让我们来看一下这个博客网站的运行效果吧:
上图中我点击了“如何马上实现财富自由”这个博客,进入到博客详情页时浏览器没有重新向服务端请求博客详情的HTML文件,而是直接在浏览器完成渲染,用户体验非常之流畅。这其实是Gatsby应用的一个很大的亮点,那就是:Gatsby打包的应用在浏览器首次请求获得提前生成的静态HTML文件后,会演变成一个React SPA应用,接下来的用户交互就和一般的SPA应用没有任何差别了,换句话来说,Gatsby既保留了SSR方案SEO友好的优点又保留了SPA应用的流畅用户体验,可谓是各取所长,扬长补短了!
其实JAMStack的应用现在已经有很多了,只不过我们平时没有留意到而已。举个例子,React开发者十分熟悉的React官网reactjs.org就是用Gatsby构建。那么除了这些比较简单的文档性和博客网站,JAMStack可以用来构建复杂的商业应用吗?答案是肯定的,除了一些简单的CMS平台,JAMStack还可以用来搭建诸如braun这类电商平台,你可能想不到的是著名的程序员学习网站freeCodeCamp也是使用JAMStack技术栈来搭建的,大家可以去网上(Google)查一下关于freeCodeCamp架构设计的视频或文章,看完之后我相信你会对JAMStack有更深入的理解的。
在上面的介绍中我已经大概说了一些JAMStack的优势了,其中包括SEO友好还有流畅的用户体验,那么除了这些,JAMStack还有没有其它吸引人的地方呢?
为什么JAMStack是高性能的呢?这是因为JAMStack的应用将网站的静态部分和动态部分区分开来了,那些不会频繁发生变化的内容会被提前生成,从而无需使用额外的计算资源来进行服务端渲染。这样用户首次访问某个页面的时候速度会变得很快,而且这些静态的资源还可以被放在CDN来进一步提升用户体验。将动态内容和静态内容区分开来还有另外一个好处,就是我们后端接口的职责更加明确了,API接口的数量会变得更少,性能也会变得更好。
由于我们前端的内容都是一些静态的文件没有服务端渲染的要求,而静态资源服务器对性能的要求并不高,所以我们在购买服务器方面不需要很大的成本,我们甚至还可以使用一些诸如netlify和Gatsby Cloud等免费资源来托管我们的文件。对于后端来说由于我们已经将前后端彻底分离了,所以后端可以使用一些廉价的Baas或者Serverless服务,例如可以使用Auth0作为我们的用户鉴权服务,使用Firebase作为我们的接口服务等等。使用这些Baas和Serverless服务有一个好处就是它们很便宜,而且它们是按照接口使用量来收费的,你的用户量决定了你的支出,如果你的用户很少,你甚至不需要花一分钱。
除了极高的性价比,JAMStack还有很好的扩展性。举个例子,假如你现在的博客网站因为某一篇博客突然火了,访问用户激增。如果你的前端静态文件使用的是CDN网络的话,你的网站很容易就可以扩展了,一切都是自动的,无需你做任何东西,而后端如果你使用了Serverless和Baas的解决方案的话,一切也是自动的,用户不会感觉到有使用体验的差别,而你只需要给使用到的服务平台多一点点费用而已。
拿我们前面提到的Gatsby来举例,它就允许我们使用一些现代的前端技术来进行开发,例如React,Styled-components和GraphQL等,这些都是我们前端开发者十分熟悉的技术了,没有很大的学习成本所以开发者体验会很好。除此之外,由于Gatsby使用了React,所以它间接上接入了React的生态系统,这样开发者在开发Gatsby应用时就可以使用React生态的各种最佳实践和库实现了,这无疑可以大大提高我们的开发效率。
由于JAMStack是一种前后端分离的技术,没有了后端渲染所以可以降低被攻击的风险。举个例子采用Gatsby生成的CMS平台就比传统的WordPress平台安全很多:)。
既然JAMStack有那么多好处,我们是不是一把梭在所有的项目中都使用JAMStack呢?答案是否定的,由于JAMStack需要我们将网站的静态部分和动态部分区分开来,静态部分的内容会在构建的时候就生成而动态的内容会在浏览器进行渲染,这个特点就注定了它不适合于构建以下类型的应用:
相反JAMStack十分适合构建以下类型的应用:
当然了我在这里列出来的无论是适用还是不适用JAMStack的应用其实都是一些很笼统的分类,我们在实际开发时还得具体问题具体分析,根据实际情况来评估我们的应用是不是适合使用JAMStack来开发。
在最后我想说一下我自己对JAMStack的一些思考。
首先我个人十分看好这个技术栈,也会在日后的开发中使用这个技术栈。因为它帮我解决了网站SEO的问题。在不了解JAMStack之前,如果我想我的网站被搜索引擎收录要么就是刀耕火种地硬写HTML和原生JS,这种方案明显开发效率十分低下。还有一种方案就是我使用React等现代开发技术,这样我就得学习next.js等SSR技术来实现SEO,这个方案有一个问题就是学习next.js有一定的学习成本,而且在项目上线后我得维护一个后端服务来进行服务端渲染,所以会有一定的运维成本。可是使用了JAMStack或者说是Gatsby后这些问题就迎刃而解了,因为我可以继续使用我熟悉的React技术栈来快速开发Web应用,还无需考虑服务端渲染的问题就可以达到SEO的效果,这不是美滋滋?
其次我觉得JAMStack这个技术栈十分有利于我们实践一些自己想到的不确定能不能成功的点子(创业想法)。上面在介绍JAMStack优势的时候,我提到了一点就是使用JAMStack其实你可以免费部署你的应用,因为你可以将前端的静态代码放在一些免费的静态资源托管服务器,然后后端使用一些免费的Baas API服务,当然了这只适合于我们平台用户量不大的情景,当用户量大的时候我们还是得付费的。可是我们网站刚起步的时候用户量不都是不大的吗?如果我们一大早就买好服务器资源和域名,后面却发现这个想法根本行不通的话,这些钱就算是赔进去了。相反,使用免费服务的话,即使我们做的东西黄了,我们也不会有什么损失。
总的来说我对JAMStack这个技术栈是很有信心的,特别是在CMS内容管理平台这方面我相信它一定会逐渐火起来,而且有可能可以取代WordPress的地位。