你给我翻译翻译,什么他妈的叫他妈的JAMStack!

862 阅读39分钟

一、让子弹飞

以下片段摘自姜文《让子弹飞》中的一段,不过请放心,没看过这部电影也丝毫不会影响你阅读这篇文章。

黄四郎:三天之后,一定给县长一个惊喜。

张麻子:汤师爷,他是胡万的恩人,现在又成了你的恩人。你给翻译翻译,什么叫惊喜?翻译翻译,什么叫惊喜?

汤师爷:这还用翻译,都说了。

张麻子:我让你翻译给我听,什么叫惊喜?

汤师爷:不用翻译,这就是惊喜啊。

黄四郎:难道你听不懂什么叫惊喜?

张麻子:我就想让你翻译翻译,什么叫惊喜!

汤师爷:惊喜嘛。

张麻子:翻译出来给我听,什么他妈的叫惊喜!什么他妈的叫他妈的惊喜!

汤师爷:什么他妈的叫惊喜啊?

黄四郎:惊喜就是三天之后,我出一百八十万给你们出城剿匪,接上我的腿!明白了吗?

汤师爷:这就是惊喜啊。

张麻子:翻译翻译!翻译翻译!

汤师爷:惊喜就是三天之后,给你一百八十万两银子出城剿匪,接上他的腿!

张麻子:哈,大哥这他妈的惊喜啊,小弟我愿意等你三天。

黄四郎:好!

之所以用张麻子的口吻来命名这篇文章一方面是出于我对这部电影的热爱,另一方面更是出于我初次听说JAMStack时的困惑。正如黄四郎不断强调的“惊喜“一般,很多号称讲透JAMStack的文章都如同着重于它自身的架构、概念,而对它与与目前主流前端技术栈的区别以及使用其所带来的好处,也就是“一百八十万两银子”确确闭口不谈。而这篇文章就像张麻子的追问一样,就是想给读者彻彻底底的从它为何出现,解决了什么问题以及如何使用来多方面的“翻译翻译”当前国外大火的JAMStack技术栈。

二、无聊却重要的历史!

知其然也要知其所以然,我们要了解一项新技术的最好方式就是通过研究其发展历史。通过深入JAMStack的发展历史,我们不仅能知道它为什么出现,同时也可以明白它解决了什么问题,然后更进一步的帮助我们理解到底在何种情境中使用它。

下面列出了从万维网出现一直到现在WEB技术栈发展的时间线:

  • 万维网诞生 1989
  • 静态网站 1989
  • 传统动态网站(LAMP)1993
  • 单页应用(MERN)2010
  • 传统JAMStack 2015
  • 新一代JAMStack 现在

可以看到,从1993年CERN(欧洲核子研究组织)将英国物理学家Tim Berners-Lee(蒂姆·伯纳斯·李)发明的万维网免费向所有公众开放以来,在短短不到30年的时间里,WEB技术已经经历了翻天覆地的变化。今天,我们能够坐在家中,一边喝着咖啡,一边浏览这篇文章,这正是30年中无数聪明的头脑共同努力的结果。在下面的章节中,我们# 你给我翻译翻译,什么他妈的叫他妈的JAMStack!

三、万维网诞生-1989

让我们回到1989年的3月,与大多数不太清楚万维网(World Wide Wb)与互联网(Internet)区别的人所想的大相径庭的是,这时的互联网已经诞生二十余年了。然而,这时的计算机想要联接到网络上需要经过一系列复杂的操作,并且由于不同的计算机具有不同的操作系统和文件格式,使得跨平台的信息文件共享几乎不太可能。

互联网(Internet)万维网(World Wide Web)
维基百科The Internet (or internet) is the global system of interconnected computer networks that uses the Internet protocol suite (TCP/IP) to communicate between networks and devices.The World Wide Web (WWW), commonly known as the Web, is an information system where documents and other web resources are identified by Uniform Resource Locators (URLs, such as example.com/), which may be interlinked by hyperlinks, and are accessible over the Internet.
简单解释任何使用标准IP协议进行的计算机网络通讯都属于互联网透过互联网访问的,由许多互相链接的超文本组成的系统。

就在这样的背景下,为了使实验组里各国的高能物理学家能通过计算机网络及时沟通并传递信息,实验组委托Tim Berners-Lee开发一个软件,以便让分布在各国实验组成员能够把最新的信息、数据、设计图资料等及时地提供给全体人员共享,随时随地犹如大家都在一起一样同步工作。经过调研,Tim Berners-Lee总结并提交了“Information Management: A Proposal” 的文章。在这篇文章中,李希望通过一种超文本方式(Hypertext)组织信息,这些信息包括文档、图片等等,并把分布在网络上的不同计算机内的信息有机地结合在一起。在提出这个想法后的1年,也就是1990年12月25日,在CERN内,李和他的同事成功地展现了基于Web原理的HTTP代理与服务器的第一次通讯。现在WEB程序员以及千千万万各行各业的人们赖以维生的万维网正式出现在世人的面前。

1993年,CERN宣布万维网技术可以被任何人免费使用,该组织将不收取和此项技术相关的任何费用。

四、静态网站 - 1989

4.1 背景

1989年,在万维网诞生之初,静态网站就已经出现了。没错,由Tim Berners-Lee所开发的第一个网站在当时就是使用静态网站架构,这个简单的网站目前仍然可以访问(info.cern.ch)。可以看到,该网站完全是由一些静态的HTML文件和a标签跳转链接构成。而要完全看到现代意义上静态网站的雏形,我们仍然需要几年的时间来让WEB前端三大技术也就是HTML、CSS、JavaScript浮出水面。

HTML的诞生

1982年,万维网的发明者Tim Berners-Lee爵士为了让全世界的物理学家能够方便的进行合作与信息共享,造了HTML(HyperText Markup Language)超文本置标语言。

CSS的诞生

1994年,CSS之父Håkon Wium Lie提出了 CSS 的最初建议,并且为 HTML 样式在芝加哥的一次会议上正式提出了 CSS 。

JavaScript的诞生

1994年,安德森创立 Netscape并公开发行了 Netscape Navigator 0.9版,这是第一款面向普通用户的浏览器。但是,这个版本的浏览器只能用来浏览,不具备与访问者互动的能力。因此网景公司急需一种网页脚本语言,使得浏览器可以与网页互动。

1995年,Brendan Eich(布兰登·艾奇) 加入网景公司并被指定为“新语言”的设计师。由于Brendan对这项任务并不感冒,因此他随意的花了10天时间便把这门“新语言”的最初版本设计了出来。后来为了蹭当时大火的JAVA的热度,这门语言被改名为JavaScript。

到1995年左右,现代WEB前端所需要的三大基本技术HTML、CSS、JavaScript终于全部集齐。第一个WEB网站框架——静态网站的结构也基本确定下来。

4.2 结构

传统静态网站的结构非常简单,一个基础的静态网站只包含由万维网所连接起来的两个部分Static Web Server以及客户端Client。

静态网站

静态网站的服务器中通常只存储网站相关的静态文件,包括Html、Css、JavaScript文件等。传统静态网站的访问过程包含以下两个步骤:

  1. 用户点击或输入一个静态网站URL,浏览器发出Http请求。
  2. 服务器WEB Serve根据URL将相应的静态文件全部返回给用户浏览器,浏览器解析这些文件并展示,等待用户进一步操作。

在这一结构中,Web 服务器只充当了一个静态资源服务器的角色,每当客户端浏览器发来访问请求,它都来者不拒的建立连接,查找 URL 指向的静态页面,再返回给客户端。

随着CDN技术的出现,大量的静态网站为了提高其访问速度,转移到了CDN上进行部署。在CDN中部署的静态网站结构会略微复杂一些,但是这些复杂性基本都由CDN服务商所屏蔽,对于开发者而言其结构与传统静态网站并无不同。

什么是CDN?

CDN的全称是Content Delivery Network,即内容分发网络。CDN是构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN的关键技术主要有内容存储和分发技术。

CDN技术的细节较多且并不是本文的重点讲解内容,所以不再赘述,只需要记住一点——CDN服务商所提供的边缘节点一般为静态资源服务器,只能支持静态网页的部署。

这里,为了给后文做一个铺垫,我们将采用CDN部署的静态网站结构画在下方。(注意:这张图屏蔽了大量开发者无需关心的CDN内部结构)

CDN静态网站

CDN部署的静态网站访问过程如下:

  1. 用户点击或输入一个CDN部署的静态网站URL,浏览器发出Http请求。
  2. CND边缘服务器回源。(若此时CDN边缘服务器中有相应缓存,则跳过2、3步)
  3. 源站点服务器根据URL将相应的静态文件全部返回给CND边缘服务器,CDN边缘缓存相关静态文件。
  4. CND边缘服务器根据URL将相应的静态文件全部返回给用户,浏览器解析这些文件并展示,等待用户进一步操作。

4.3 利弊

不要以为静态网站是只存在于书中的老古董,实际上随着CSS以及JavaScript的不断发展,大量动画精美,设计精良,但确不需要动态改变数据的网站现在仍然是通过该架构实现的。

另外,静态网站还有着以下的一些优点:

  • 网页访问速度快,静态资源的特性以及CDN部署的出现都使得静态网站的访问速度几乎无人能敌。
  • SEO(搜索引擎优化)简单,几乎所有内容都在HTML文件中,便于搜索引擎爬虫的抓取。
  • 节约成本,没有后端服务使得静态网站既不需要专业人员维护复杂的后端服务,也不需要花钱提高后端服务器的承载能力。

当然静态网站也有着不容忽视的缺点:

  • 交互性较差,无法做到千人千面,也无法动态响应用户输入,在功能方面有较大的限制。
  • 内容更新复杂,哪怕只改一个字都需要修改源代码并重新部署。
  • 大型网站开发工作量大,虽然任何学过一点前端技术的人都可以在短时间内搭建起一个最基础的静态网站,但是当网站内容较多时需要完成大量的重复工作(如开发一个拥有超过10,000篇文章的博客网站)。

五、传统动态网站(LAMP)- 1993

5.1 背景

在经过早期的万维网快速发展后,人们很快就不仅仅满足于只访问放在Web服务器上的静态文件了。为了解决人民日益增长的物质文化需要同落后的网站架构之间的矛盾,1993年,一种叫做CGI(Common Gateway Interface)的新技术在美国国家超级电脑应用中心出现了。相比于静态网站,使用这种新技术的网站具有以下一些独特的特性:

交互性:网页会根据用户的需要和选择而动态地改变并响应。

自动更新:无须手动地更新部署HTML文档,程序根据需要自动生成新的页面,大大节省了网站开发所需工作量。

千人千面:不同的时间,不同的地点,不同的人访问同一网址时会产生不同的页面。

我们将这种具有交互性的,由程序根据输入动态生成的网站统称为动态网站。

5.2 结构

直到今天为止,动态网站技术已经经历了近30年的发展。在这漫漫岁月长河中,不断有新的技术浮现,也不断有旧的技术消亡。但是,如果一定要评出一个最具有代表性或者说最广泛使用的动态网站建站架构,那一定非LAMP莫属了。不过有趣的是,LAMP并非靠着一个个精通WEB技术的程序员而扬名天下的,反而是众多不懂WEB技术但却希望拥有一个自己网站的普罗大众在WordPress的帮助下,使用LAMP搭建了迄今为止占万维网总量超37%的WEB网站!

什么是WordPress?

尽管WordPress已经非常出名了,但是我相信还是有非常多的程序员从没有接触或者使用过它。简单的说,WordPress是使用PHP语言开发的CMS,也是全球使用人数最多的免费开源的建站程序。通过使用WordPress建立网站,用户无需接触任何代码,只需要根据其教程在图形化界面上做出相应的选择和配置库可以轻松的搭建起一个可以访问的页面(网站可以被托管在wordpress.com中,用户无需配置管理自己的主机)。之后通过其提供的CMS管理后台网页,用户就可以轻松修改网站所展示的内容。当然,WordPress丰富而庞大的插件系统也为其提供了强大的各类附加功能,例如轻松修改网站外观等。

什么是CMS?

CMS(Content Management System)翻译过来就是内容管理系统,顾名思义,它主要是为了方便发布网络内容而存在的一体化WEB管理系统。CMS可以理解为一种软件工具,它允许我们轻松的创建,编辑和发布各种内容。以一个新闻网站为例,通常这种网站会雇佣大批内容编辑人员来搜集整理网站的文章,但是这些人员对于WEB技术并不了解,为了避免只有程序员可以改变网站内容,就需要使用CMS来管理这个新闻网站。这个CMS至少需要有一个后台页面,编辑人员通过登录后台进入一个可视化的操作界面,把搜集到的文章录入进去,在通过审核后这些文章会自动发布更新到网站中。

LAMP实际上是一组一起使用来运行动态网站或者服务器的软件名称首字母缩写:

  • Linux,操作系统
  • Apache,WEB服务器
  • MySQL或MariaDB,数据库管理系统
  • PHP、Perl或Python,脚本语言

可以看出,从技术层面出发,LAMP相比其他架构更为流行的重要原因就是该架构所依赖的技术几乎全部是开源免费的。

LAMP

传统动态网站结构相比传统静态网站结构看起来仅仅是加入了一个数据库,并没有复杂很多,然而在Web Server中发生的事情已经发生了极大的变化。当用户访问一个LAMP搭建的动态网站时,整个过程大致如下:

  1. 用户点击或输入一个动态网站URL,浏览器发出Http请求,请求中携带构建网页所需的一些特殊参数。
  2. Apache WEB Server接收到用户请求,根据用户请求路径以及携带的参数,运行服务器中相应的PHP程序。PHP程序在执行过程中会根据请求参数访问MySQL数据库。(若不需要使用数据库中的数据,则省略第2、3步骤)
  3. MySQL数据库执行查询并返回查询结果。
  4. PHP程序根据查询结果生成HTML等显示网页所需要的静态文件,并将这些文件返回给浏览器。最后,浏览器解析文件并展示,等待用户进一步操作。

在这个流程中,用户有机会在请求中插入一些参数以控制程序生成网站的方式(不一定是直接输入参数,大多情况下都是通过JS、Form表单等形式获取用户输入),最终动态改变了网页的展现。

5.3 利弊

动态网站的出现解决了此前的多数痛苦,让WEB程序向前再次迈出了一大步:

  • 交互性有所提升,可以实现表单和一些简单交互。
  • 大型网站开发工作简便,不用编写一大堆静态页面,可以用数据库作为数据来源来展示网页内容。

不过,在解决这些问题的同时,动态网站结构也带来了另一些问题:

  • 网页总是刷新,用户名密码校验需要刷新以展示错误提示;因下拉选择器选择不同而展示的内容需要刷新才能展示;每次数据交互都必然会刷新一次页面。
  • 网页代码与后端逻辑混合,相信老前端们都有过这样的经历:开发完HTML后,会把页面发给后端修改,加上数据注入逻辑;联调或者debug的时候两个人坐在一块看,查问题的效率很低。
  • 代码重复传输无法复用,举一个典型的例子,论坛。很多时候只有内容有变化,菜单、侧边栏等几乎不会有改变,但每次请求的时候还是得再将整个网页传输一遍。不仅页面会刷新,速度慢,还挺耗流量(在那个年代上网还是根据流量或时长付费的)。
  • 成本上升,后端服务的出现使得动态网站开始需要专业人员维护复杂的后端服务,访问量较大的网站还需要在服务器的升级扩容上支出很多。
  • 无法CDN加速,因为CDN边缘节点只支持部署静态内容,无法运行PHP等程序。

这些问题在相当长的一段时间内(对于WEB技术发展来说)都没有得到完全的解决,直到AJAX、Node等技术逐步成熟并推广开后,基于这些技术的单页应用架构破土而出,将WEB从1.0时代带入了2.0时代。

六、单页应用(MERN) - 2010

6.1 背景

传统动态网站架构从出现以来快速的一统WEB开发十多年之久,其实直到今天,很多传统公司和行业的网站甚至部分互联网公司的老业务依然在采用这这种技术为数以亿计的用户提供着服务。当然,这并不代表动态网站技术毫无发展,虽然大体结构没变,但很多细节和性能已经和最初的样子大相径庭了。其中,值得一提的便是AJAX技术的出现,这项技术使得动态网站大大减少了网页的刷新频率。

什么是AJAX?

AJAX全称为Asynchronous JavaScript and XML(异步的JavaScript与XML技术),指的是一套综合了多项技术的浏览器端网页开发技术。

传统的Web应用允许用户端填写表单(Form),当提交表单时就向网页服务器发送一个请求。服务器接收并处理传来的表单,然后送回一个新的网页,但这个做法浪费了许多带宽,因为在前后两个页面中的大部分HTML码往往是相同的。由于每次应用的沟通都需要向服务器发送请求,应用的回应时间依赖于服务器的回应时间。这导致了用户界面的响应比本机应用慢得多。

与此不同,AJAX应用可以仅向服务器发送并取回必须的数据,并在客户端采用JavaScript处理来自服务器的回应。因为在服务器和浏览器之间交换的数据大量减少,服务器回应变得更快了。同时,很多处理工作可以在发出请求的客户端机器上完成,因此Web服务器的负荷也减少了。

另外一个里程碑式的事件发生在2009年,随着Ryan Dahl发明了Node.js,JavaScript终于从最初咿呀学语的婴儿成长为拥有了服务端编程能力的屠龙勇士。

什么是Node.js?

Node.js是一个服务器端 JavaScript的运行环境,可以通过使用JavaScript和其提供的一系列模块来编写服务器端以及网络相关的应用。它的核心模块包括文件系统I/O、网络(HTTP、TCP、UDP、DNS、TLS/SSL等)、二进制数据流、加密算法、数据流等等。Node模块的API形式简单,降低了编程的复杂度。

Node.js主要用于编写像Web服务器一样的网络应用,这和PHP和Python是类似的。但是Node.js与其他语言最大的不同之处在于,PHP等语言是阻塞的(只有前一条命令执行完毕才会执行后面的命令),而Node.js是非阻塞的,基于事件循环和回调极致的(多条命令可以同时被运行,通过回调函数得知命令已结束运行)。

有了这两个基础技术作为铺垫再加上一些聪明头脑的努力,终于形成了今天前端程序员最常见、也是最长使用的单页应用式架构。(注意:并非2010年才出现单页应用这个概念,只是这时才比较成熟。)

6.2 结构

目前比较著名的单页应用式架构简称为MERN架构,与LAMP相同,它也是一组一起用来运行单页式应用网站或者服务器的软件名称首字母缩写:

  • MangoDB,非关系型数据库管理系统
  • Express,Node.js的服务器端框架
  • React,前端(客户端)JS框架
  • Node.js,服务器端 JavaScript 运行环境

从技术角度出发,MERN架构代表了JS程序员们终于可以摆脱桎梏,独立完成WEB开发的全部流程。这里,作为一名前端开发,我的内心促使我不得不写下这句著名的Atwood's Law。

Any application that can be written in JavaScript, will eventually be written in JavaScript.

任何可以使用JavaScript来编写的应用,最终都会由JavaScript编写。

当然,这里我们并不想讨论这句话的对错。相反的,我想告诉读者,虽然MERN结构式一种实现单页应用的著名架构,但是在实际的互联网业务开发的工作中,涉及到后端的MangoDB、Express、Node.js大概率还是会被JAVA程序员们替换成MySQL、SpringBoot、Tomcat等工具。不过,工具的替换并不会影响网站的结构,因此我们这里仍然以MERN为例来阐述整个单页应用的结构。

MERN

从结构上来看,MERN架构相比LAMP架构只是多出了一个Static Server(静态资源服务器)。当用户访问一个MERN搭建的单页应用网站时,整个过程大致如下:

  1. 用户点击或输入一个单页应用网站URL,浏览器发出Http请求。
  2. Static Web Server接收到用户请求,根据用户请求路径返回相应静态资源,包括一个空白的HTML文件以及相应的JavaScript文件。浏览器接收到文件后解析空白HTML并运行JavaScript文件,需要注意的是在这个JavaScript文件中我们使用了React框架,因此浏览器中的DOM树会被React动态创建出来,最终用户侧展现的是运行React程序后的页面样式
  3. 执行JS过程中,有可能需要根据数据库中的数据来生成相关DOM,此时JS控制浏览器发出一个或多个AJAX请求。(若不需要使用数据库中的数据,则省略当前及以下步骤,直接展示结果)
  4. Express Web Server接收到AJAX请求,Node.js程序根据其路径及参数向MangoDB库发起相关查询。
  5. MangoDB执行查询并返回查询结果。
  6. Express Server收到查询结果,Node.js程序处理数据并将其返回给浏览器。浏览器中的JS监听到AJAX的返回,执行相应React程序,通过DOM操作新增/替换/删除部分DOM。最后,浏览器展示最终渲染结果,等待用户进一步操作。

在整个网站的访问过程中,浏览器一般只会收到一份空白的HTML文件,所有的DOM元素都是使用React框架执行的JS动态在客户端创建出来的。

6.3 利弊

单页应用的出现解决了传统动态网站的不足之处:

  • 网页不需要刷新,不管是数据的提交还是站内页面的跳转都不再需要刷新页面。
  • 网页与服务器代码彻底分离,只要定好AJAX接口格式,前端可以与后端程序员完全并行的开发网站。
  • 只传输必要的数据,AJAX请求只需要携带前后端交互必须的数据,减缓了网络压力。
  • 成本下降,页面在客户端构造,服务端不再关注HTML的构造,降低了服务器的压力。
  • 可以CND加速,可以将CDN边缘节点当作MERN结构中的静态资源服务器。

但是,这个世界上是没有十全十美的事情的,即便放在技术上也是如此:

  • 首次加载耗时长,因为需要等待JS执行后动态创建网页DOM。
  • 搜索引擎优化极不友好,由于网页上的所有内容都是通过JS动态创建的,在搜索引擎爬虫只爬取网站HTML时就无法获取有用的信息,从而网站排名被降低,这点对于某些商业网站是致命的!

正如萧伯纳所说“科学始终是不公道的。如果它不提出十个问题,也就永远不能解决一个问题”。正是因为单页应用并不完美,在之后的日子里JAMStack架构才被提出。

七、传统JAMStack - 2015

7.1 背景

传统JAMStack架构并不是为了打败MERN单页应用架构而出现的,JAMStack在早期完全可以被看作是一个为了打败WordPress这种采用传统LAMP架构的CMS厂商,从而提出以用来实现产品差异化的一个商业概念

当然,与前文相同的是在整体架构发生大的调整或改变前,一些解决相关问题的技术一定会提前出现。而这一次出现的技术就是SSG。

什么是SSG?

SSG全称为Static Site Generation(静态网站生成器),是一种帮助用户根据其模版(例如markdown文件)以及相关数据(例如磁盘内存储的文件)应用一定的规则从而自动生成静态网站的工具。

与传统动态网站如LAMP架构中的网站生成不同的是:在LAMP中,运行在WEB Server中的PHP程序会在用户访问网站时生成相应页面;而在SSG中,页面会打包部署时构建出来,之后用户访问到的都是提前生成好的静态页面。

SSG难道不是倒退回了静态网站时代吗?

从网站最终部署的架构上来看是这样的,但是从其使用上来看又不是。

我们来看这样一个场景,一个购物网站最开始可能只有10件商品,这时我们可以轻松的为每一件商品编写一个静态的HTML文件作为其展示页面。然而,突然有一天,这个网站火爆了起来,于是我们决定再上架1000件商品,这时难道我们需要编写1000个大体结构差不多但商品详情不同的HTML页面吗?当然不是!通过编写一个模版并且将1000个商品的信息录入一个文件中,使用SSG可以帮助我们轻松生成这1000个不同商品的展示页面。

随着Ajax的发展,CMS服务商也与时俱进的推出了Headless CMS这个新概念。

什么是Headless CMS?

Headless CMS一般被翻译为“无头”CMS,这里“无头”是指在Headless CMS中,我们将传统CMS中给用户展示的前端网站(头部)砍掉,只剩下后台管理系统和一组对外提供服务的API(身体)。正式因为Headless CMS将展示外观与内容管理进行了完全的解耦,这使得我们有能力针对不同的设备、用户或者使用场景对同样的内容采用完全不同方式展现出来。

需要关注的是,Headless CMS这种模式被称为API-driven(API驱动)。

在这样的背景下,传统JAMStack架构在2015年左右被Netlify的CEO Mathias Biilmann首次提出。

7.2 结构

JAMStack正如前文所有的技术一样,秉承了将首字母缩写合并在起名一起的传统:

  • JavaScript
  • API
  • Markup

这三个单词所代表的并非是某几个专门的技术或者框架,而是非常笼统地囊括了几乎前端所能涉及到的所有领域,所以我们很难简单的从这个词中就了解到JAMStack所用的技术和结构。不过,这可能也是JAMStack的发明者所希望的,作为一个所谓的“现代”WEB架构(这可不是我说的,而是其发明者说的),JAMStack并不希望将自己局限于某几个可能仅仅一时流行的技术之中。

传统JAMStack

这里我们给出一个典型的传统JAMStack结构示例,与前述章节架构不同的是JAMStack架构在整个网站的生命周期中不止作用于用户访问网站的过程中,同时也作用于网站部署的过程中,因此我们的示例图中多出了网站生成的过程。

搭建一个传统JAMStack结构网站的过程如下:

  1. 开发者上传代码至github(这一过程对于不懂编程的人员也可以是CMS厂商提供的一些代码模版),并在Headless CMS后台管理系统中输入网站中希望展现的内容。

  2. SSG被触发,拉取github中的代码与Headless CMS中的内容并将其结合,从而生成静态网站。

  3. 静态网站上传并部署在CDN上。(过程3、4一般由CMS厂商通过相关技术自动完成,开发者无需手动处理)

访问一个传统JAMStack结构网站的过程如下:

  1. 用户点击或输入一个JAMStack结构网站URL,浏览器发出Http请求。

  2. CND边缘服务器回源。(若此时CDN边缘服务器中有相应缓存,则跳过5、6步)

  3. 源站点服务器根据URL将相应的静态文件全部返回给CND边缘服务器,CDN边缘缓存相关静态文件。

  4. CND边缘服务器根据URL将相应的静态文件全部返回给用户,浏览器解析这些文件并展示,等待用户进一步操作。

可以看到,JAMStack结构的网站在部署后,其结构与传统CDN中部署静态网站的结构并无二致。

7.3 利弊

可以看到CMS厂商在传统JAMStack架构的出现中起到了弥足轻重的作用,相比于WordPress这种采用传统LAMP架构CMS厂商的产品,采用JAMStack架构的产品有着一系列的好处:

  • 网页访问速度快,传统JAMStack架构的网站在部署时与静态网站类似,只需要部署静态文件,访问速度快。

  • 节约成本,没有后端服务使得静态网站既不需要专业人员维护复杂的后端服务,也不需要花钱提高后端服务器的承载能力。

  • 大型网站开发工作简便,不用编写一大堆静态页面,可以用Headless CMS作为数据来源来展示网页内容。

  • 内容更新简单,只需要改变Headless CMS中的内容,网站就会自动构建并部署。

传统JAMStack的劣势与静态网站类似:

  • 交互性较差,无法做到千人千面,也无法动态响应用户输入,在功能方面有较大的限制。

八、新一代JAMStack - 现在

8.1 背景

传统JAMStack网站在部署后与静态网站几乎一致,这导致了它在交互性等方面存在着无法接受的短板。不过,在经过了几年的发展之后,JAMStack架构从一个最初CMS厂商提出的商业概念逐步发展转换,真正成为了业内火热的下一代建站技术。现在所提到的JAMStack几乎都是指新一代JAMStack。

新一代JAMStack在传统JAMStack所采用技术的基础上,更进一步采用了SSR以及Servless技术。

什么是SSR?

SSR全称为Server-Side Rendering(服务端渲染),是指由服务器端运行相关JS完成页面的HTML结构拼接处理后再将页面发送到浏览器进行展示的技术。与SSR相反的是CSR(也就是Client-Side Rendering客户端渲染),CSR是指服务器将页面相关的JS文件以HTML模板直接返回给浏览器,在浏览器中运行JS完成最终页面的HTML结构拼接处理。可以看出,两者间最明显的区别就是构建HTML结构的JS文件是在服务端还是客户端运行的。

SSR其实并不是一个全新的技术,传统动态网站(如LAMP)都是服务端渲染的。之所以这个概念在这些年被再次提出并讨论,是因为对于传统SPA网站(如MERN)来说,它们都是客户端渲染的,然而客户端渲染存在着首屏渲染时间长、SEO优化困难等缺点,因此我们希望能够改变传统SPA网站的渲染方式,使其也能够支持SSR渲染。目前流行的三大SPA前端JS框架React、Vue、Angular都已经有了成熟的SSR方案。

什么是Servless?

Servless译为无服务器,是是一种云原生开发模型,可使开发人员专注构建和运行应用,而无需管理服务器。

简单地说,使用Servless技术可以让开发人员从繁琐复杂的服务器管理维护中解脱出来,开发人员只需要专注于自己开发模块的业务逻辑,其余的事情(包括扩容、部署、容灾、监控、日志、安全补丁等)都可以交给云服务商处理。这里我们不再深入研究Serveless技术,只需要知道我们可以将网站的后端以及数据库都以Serveless的方式部署,想了解其更多详情可以参考Red Hat的这篇文章什么是无服务器

新一代JAMStack与传统JAMStack的出现时间并无明显界限,是逐渐演变而来的。

8.2 结构

在JAMStack的官方网站上(jamstack.org/what-is-jam…

Jamstack is an architecture designed to make the web faster, more secure, and easier to scale. It builds on many of the tools and workflows which developers love, and which bring maximum productivity.

Jamstack 是一种旨在使 Web 更快、更安全且更易于扩展的架构。它建立在开发人员喜爱的许多工具和工作流程之上,从而最大化提升了生产力。

The core principles of pre-rendering, and decoupling, enable sites and applications to be delivered with greater confidence and resilience than ever before.

Jamstack的核心原则是预渲染和解耦,这使得站点和应用程序的可靠性以及可拓展性达到了前所未有的高度。

可以看到,新一代JAMStack与之前一样,并非必须要使用某一项或几项技术。不过为了让我们更好的理解它是什么,我们这里同样给出一个完整且典型的新一代JAMStack结构示例。(某些JAMStack结构的网站可能只实现了其中的一部分,这并无不妥)

新一代JAMStack

搭建一个现代JAMStack结构网站的过程如下:

  1. 开发者上传代码至github,并通过一些方式使用Serveless API将网站中希望展现的内容存储在Serveless数据库之中。

  2. SSG被触发,拉取github中的代码与Serveless API从数据库中取出的内容结合,从而生成静态页面文件。

  3. 静态页面及相关文件上传并部署在Serveless服务器上。

访问一个现代JAMStack结构网站的过程如下:

  1. 用户点击或输入一个JAMStack结构网站URL,浏览器发出Http请求。

  2. CND边缘服务器回源。(若此时CDN边缘服务器中有相应缓存,则跳到第11步)

  3. 源站点服务器查看是否有URL相应的静态缓存,若没有则请求Serveless服务器。(若已有缓存,则跳到第10步)

  4. Serveless服务器根据URL调用Serveless API。

  5. Serveless API查询数据库并返回相应结果,Serveless服务器将SSG生成的静态页面文件以及Serveless API返回的结果相结合,通过SSR进一步渲染出新的静态页面文件。

  6. Serveless服务器据URL将相应的静态文件全部返回给源站点服务器,源站点服务器缓存相关静态文件。

  7. 源站点服务器根据URL将相应的静态文件全部返回给CND边缘服务器,CDN边缘缓存相关静态文件。

  8. CND边缘服务器根据URL将相应的静态文件全部返回给用户,浏览器解析这些文件。在执行JS过程中,有可能需要根据数据库中的数据来生成相关DOM,此时JS控制浏览器发出一个或多个AJAX请求。(若不需要使用数据库中的数据,则省略当前及以下步骤,直接展示结果)

  9. Serveless API接收到AJAX请求,根据其路径及参数向数据库库发起相关查询并拿到结果。

  10. Serveless API将数据返回给浏览器,浏览器通过CSR生成最终的渲染树并展示最终渲染结果,等待用户进一步操作。

新一代JAMStack结构的网站大量使用了云相关技术,避免了大量繁琐昂贵的服务器维护工作(灰色背景部分都可以部署在云端)。当然,这些部分也完全可以选择使用传统服务器。

8.3 利弊

可以看到新一代JAMStack结构的网站被称为下一代建站技术并不是空穴来风的,这个架构通过使用SSG/SSR/CSR、Serveless、CDN等技术,将单页应用网站、传统动态网站以及静态网站的优点结合在了一起,并且尽量避免了它们单独使用时的缺陷。

新一代JAMStack结构网站的好处主要有:

  • 只传输必要的数据,AJAX请求只需要携带前后端交互必须的数据,减缓了网络压力。

  • 只花费必要成本,一方面可自由调整页面在客户端还是服务端渲染从而调节服务器压力,另一方面Serveless提供了按需使用并付费的能力。

  • 网页访问速度尽可能的快,开发者有能力控制网页的渲染时机,在交互性与访问速度之间做出平衡。

  • 网站开发工作简便,支持React/Vue/Angular等前端框架的开发方式,学习成本低,开发效率高。

  • SEO(搜索引擎优化)简单,可控制关键信息为SSG或SSR渲染,便于搜索引擎爬虫的抓取。

但凡事并无绝对,新一代JAMStack也有其不适用的地方:

  • 不适合千人千面的网站,由于大量内容都需要CSR渲染,在这种网站中,使用JAMStack与使用SPA并无本质区别。
  • 开发人员要求较高,开发者不止是前端开发角色,也需要对云技术、后端开发等相关技术有所了解。

九、JAMStack使用

读到这里,我们已经对JAMStack大概有了一些印象,那我们究竟要如何在自己的项目中使用JAMStack呢?由于JAMStack并不能也不希望于局限于一种或几种技术,因此这个问题很难有一个定论。比如对于Serveless API部分,我们既可以使用自己编写部署的Lambda函数,也可以使用Headless CMS。对于CSR渲染部分,我们既可以使用React这种SPA前端框架,也可以使用传统JQuery自己实现。对于SSG工具,我们既可以选择Gastby一键建站,也可以选择自行编写相关代码。

不过,我们可以通过Next.js这个REACT开发框架来感受一下一个JAMStack结构网站的核心部分应该提供什么能力以及如何编写。

9.1 什么是Next.js

Next.js是目前star数最多的在Jamstack结构网站开发中所使用的框架。在Next.js官网上,官方将其描述为“这是一个用于生产环境的 React 框架”。单看这句话我们很难理解它到底是什么,所以官网也贴心的将它的一些特性列举在了下方:

Next.js特性

它的这些特性,尤其是“混合模式:SSG和SSR“、“增量静态生成”使其非常符合JAMStack所提到的预渲染核心原则。简而言之,Next.js提供了一种混合渲染方式,使得开发者有能力精细控制页面的不同部分采用不同的SSG/SSR/CSR渲染策略。

9.2 如何控制渲染

SSG

通过导出getStaticProps方法,该方法将在网站构建生成阶段被调用。方法支持开发者在这个阶段访问文件系统、API、数据库等获取构建网站所需的动态数据。

export default function Home(props) { ... }

export async function getStaticProps() {
  // Get external data from the file system, API, DB, etc.
  const data = ...

  // The value of the `props` key will be
  //  passed to the `Home` component
  return {
    props: ...
  }
}

SSR

通过导出getServerSideProps方法,该方法将在每次页面请求时被调用。该方法具有一个context参数,开发者可以从中获取当前请求参数等相关详细信息。方法支持开发者在这个阶段访问外部API等获取服务端渲染所需的数据。

export default function Home(props) { ... }

export async function getServerSideProps(context) {
  // Fetch data from external API
  const res = await fetch(`https://.../data`)
  const data = await res.json()
  
  // The value of the `props` key will be
  //  passed to the `Home` component
  return {
    props: { data }
  }
}

CSR

如下所示,与基础React应用并无区别。

export default function Home(props) {
  // Fetch data from API
  const res = await fetch(`https://.../data`)
  const data = await res.json()
  
  return (
    <>
    	{{ data }}
  	<>
  )
}

可以看到,在Next.js中控制渲染非常简单,采用了一种类似于生命周期钩子的方式,并不需要开发者关注其底层具体实现。

十、写在最后

10.1 我怎么没听说过?

JAMStack从出现至今已经有5年有余了,并且已经被很多大型公司广泛使用,目前看来已经成为真正意义上最可能的下一代WEB架构,但是无论是身边同事的了解还是网上中文资料的数量都远远显示不出它目前的火热程度。这点可以从JAMStack官方调查中的统计数据中看出其原因。下图是2020-2021年度JAMStack开发者的开发年限以及地区的统计,可以看到,无论开发年限的长短,JAMStack开发者的所在地区主要集中在欧洲以及北美,而代表东亚开发者的橘色部分占比极小。

JAMStack调查

所以,不能因为JAMStack目前在国内并不流行就轻易否定它,作为一个开发者我们应该打破地域限制,尽量提升自己的视野。

10.2 想进一步学习?

这篇文章只能带你对JAMStack有一个初步的印象,想要更近一步的系统学习JAMStack,这里最推荐的就是它的官方网站jamstack.org/。

此外,由于JAMStack并不局限于一种或几种特定的技术,所以学习JAMStack不仅可以了解一种WEB架构,还能够了解到云技术、后端技术、数据库等等几乎WEB相关的所有内容。