Web 应用程序 - 我的心理备忘单
简介
本文是“持续交付:从 HTML 到 Kubernetes”的一部分。
尽管我迫不及待地想了解分布式系统的细节,但我发现自己处于一个不愉快的境地:我认为最好从写前端开始。
这是因为Web 应用如今已成为标配。无论你在多个云中部署的 ArgoCD-Kubernetes 集群中有多少个 3000 个微服务,如果用户无法或不愿使用你的产品,那么这些都毫无意义。
为什么在浏览器中
说在浏览器中交付软件越来越流行,这显然不公平。哎,现在浏览器几乎成了所有软件的默认设置。Adobe把 Photoshop 搬到了网页上。
好吧,这是一个极端的例子。尽管我们仍然会开玩笑说 JS 的世界每周都在变化,但 Web 应用的普及率却在不断增长。尽管JavaScript 的生态系统已经达到了顶尖水平,我们仍然可以这么说。
因此,现在默认的做法是通过互联网来交付软件,即跨平台运行一切的银弹browser
。
强大的力量带来巨大的复杂性
但这究竟意味着什么呢?
- 像维基百科这样的“简单网站”和可以“安装”在手机上甚至向您发送通知的功能齐全的网络应用程序之间有什么区别?
- 或者当您没有有效的互联网连接时您可以与之交互的应用程序?
- 服务器端渲染和客户端渲染有何不同?
- 它是纯静态的 HTML 吗?还是由服务器生成并直接返回的?
- 在同一个网站内切换页面时浏览器是否会闪烁?
- 当您从 Web 应用程序内部访问相同的 URL 时,与您在浏览器的 URL 栏中按 Enter 键时的行为是否相同?
- 我们可以用 SSR 来实现 PWA……就这么做吧,对吧?对吧?!
问题很多,选择也很多。这是我的思维模型——它可以作为“WebApps 相关的复杂性和何时使用的速查表”。
您在表格中看到的“总体复杂性”是我认为构建、维护、演进、测试和交付此类应用的复杂性的总和。这不仅是在最初的 3 个月或 6 个月内,而且随着时间的推移:
- 当需求发生变化时
- 常用浏览器何时更新
- 当库不再与常用浏览器兼容时
- 当你需要更新上述库时
- 当安全补丁
- 当 X
- 当 Y
- 什么时候…
这个清单还可以继续列下去。
我认为,除了简历膨胀之外,没有理由为需要实时数据的管理界面创建具有离线功能的 PWA。这只是一个例子。
虽然每种类型的应用程序都有各自的优缺点,但我认为值得研究的是,交付应用程序的复杂程度、它能做什么以及它应该做什么。
请注意,我的列表是自行构建的:最简单的“Web 应用程序”是一个静态 HTML 文件,而最复杂的是一个成熟的 PWA。
WASM 本身就是一个庞然大物——这里就不详细介绍了。
静态 HTML
我列表中的第一个是经典的static HTML
。它代表了网络的起源:html
当用户点击时,服务器会提供一个简单的文件URL
。
这个过程非常简单:
- 用户
site.com
在浏览器中输入 URL 栏。浏览器(经过一番DNS
操作后)会向服务器发出请求。 - 服务器接收请求,处理它,并返回响应:
html
文件。 - 浏览器接收
html
文件,甚至可能请求初始文件中引用的其他文件(css
、js
)。浏览器读取整个文件并显示其内容。 - 用户在浏览器中查看信息。简洁、优雅、美观。
在幕后,开发人员编写并将文件传送到服务器的工作过程如下:
开发过程也很简单:只需编写html
、css
、js
文件,将它们“链接”在一起,然后部署到服务器即可。无需复杂的 IDE,也无需编译。
✅优点:易于开发,无需工具,加载速度快,兼容所有浏览器
⚠️ 我考虑的
js
是轻量级或无。对于 JS 密集型网站,请参阅我对SPA的定义。
❌缺点:代码不可重用(例如页眉、页脚等)、用户不可知(向每个人显示相同的数据)。
❗ 如果您希望 js 和 css 在任何地方都能正常工作,那么跨浏览器兼容性就不那么好 :)
静态站点生成器
对于代码可重用性等简单问题static HTML
,静态站点生成器可以发挥作用并解决问题。
❗ 警告:开发人员在交付网站之前需要进行额外的构建步骤。
虽然请求处理看起来与以下内容相同static HTML
:
开发过程需要额外的步骤:
虽然这并非最复杂的情况,但仍然值得注意的是,现在只需简单刷新浏览器,开发人员就无法看到最终结果。除非本地服务器支持热重载,或者手动运行构建。
✅优点:加载速度快,并且在静态内容工作负载的可重用性方面具有可扩展性。
❌缺点:与用户无关,在部署网站之前需要额外的构建步骤(与相比)。static html
服务器生成的 HTML
那么需要身份验证的网站怎么办?并且需要显示已登录用户的信息?
纯粹static html
或者static site generators
不再削减它。
我们现在正在转向“现实世界”的网络功能,它server
不再只是一种愚蠢的内容传递机制。Server
现在指的是一台成熟的机器,它也能够处理请求。
(点击此处查看更高质量的视觉效果)
从用户的角度来看,这与静态网站完全相同。然而,对实际情况更完整的描述如下:
- 用户
site.com
在浏览器中输入 URL 栏。浏览器(经过一番DNS
操作后)会向服务器发出请求。 - 正在
server
监听连接,并收到新请求。 - [可选] 根据应用程序的逻辑,它可能会调用其他服务:数据库、电子邮件、身份验证等。
- 服务器将所需信息传递给
templating engine
,后者将templates
(由开发人员定义)+variables
(由“传入”server
)=> 转换为html
文件。 - 浏览器接收
html
文件,甚至可能请求初始文件中引用的其他文件(css
、js
)。浏览器读取整个文件并显示其内容。 - 用户在浏览器中看到信息,但不知道背后发生了什么。
比静态网站功能强大得多,但也更昂贵。它需要的资源比简单的纯内容交付服务器多得多。就开发成本而言,它也更昂贵:虽然static html
和static site generators
的唯一要求是理解html
,但现在的“知识门槛”更高了。
(点击此处查看更高质量的视觉效果)
现在你需要一个local dev server
,这样你就可以有一个反馈循环并测试你的更改。理想情况下,它保持同步,并且像生产环境一样工作。这会增加大量的复杂性。
构建步骤可能看起来与静态站点生成器中的构建步骤类似,因为您仍然需要在部署过程中复制一堆文件;但是,对于某些服务器端语言,还有一个额外的编译步骤。
为监听请求的守护进程添加配置 - 恭喜,您现在有一个复杂的设置需要维护。
✅优点:可重用性(由于模板引擎,类似于静态站点生成器),可以返回用户个性化响应。
❌缺点:在开发 - 部署 - 维护方面比静态响应复杂得多,每次处理请求都需要额外的资源。
单页应用程序
对于server-side generated html
,对于每个请求,服务器都需要做额外的工作来处理它并返回html
浏览器将要渲染的所有内容。这意味着服务器需要做额外的工作,并且需要通过(可能不可靠/缓慢的)网络发送大量的响应(整个html
标记)。更糟糕的是,当浏览器加载新页面时,用户看到的是一个空白页。
(点击此处查看更高质量的视觉效果)
如果我们能够解决所有这些问题并减少以下问题,那不是很好吗:
- 用户需要等待页面加载的时间(不适用于首页加载,实际上可能更慢)
- 服务器上的负载 - 通过删除模板并仅返回
dynamic
部分数据 - 通过网络发送的有效载荷的大小
- 部署量子的大小
这就是 SPA 发挥作用的地方,它可以解决上面提到的所有问题:
(点击此处查看更高质量的视觉效果)
然而,这并非毫无代价。我们获得了额外的复杂性:当然,这在开发过程中是必要的,但现在我们还必须开始考虑对请求处理的影响。
让我们看看通常的 SPA 是如何加载并处理请求和显示数据的:
(点击此处查看更高质量的视觉效果)
- Alice
site.com
在浏览器的 URL 栏中输入网址。浏览器(经过一番DNS
操作后)会向服务器发出请求。 - 服务器接收请求、处理请求并返回响应:
html
文件。 - 在这种情况下,可以安全地将
html
服务器返回的初始文件视为空壳。它通常是一个带有空 元素的空白页面div
,将由实际应用程序使用。 - 该
html
文件引用了应用程序代码,因此浏览器将对该文件发出新的请求app.js
。 - 浏览器接收并开始处理文件
js
。根据文件大小,可能需要一段时间…… - 现在,我们终于有一个 SPA 被浏览器加载并运行了。它可能会给 Alice 一些提示,表明它开始为她做一些工作(在本例中,就是收集显示她姓名所需的信息)。
Client-side hydration
:然后应用程序将进行异步调用API server
(就我们关心的而言,可能也是提供静态文件的同一个调用)。- 当它返回信息(“Alice”)时,浏览器可以隐藏加载指示器并呈现页面。
- Alice 现在可以与已加载的应用程序进行交互。
几点说明:
仅当 Alice首次进入应用程序时才需要完成步骤 1 至 6 。
dumb content-delivery server
为了清楚起见,我对和进行了明确的区分API server
——没有什么可以阻止您设置服务器来提供静态内容并响应 API 请求。❗ 并非所有 SPA 的工作原理都相同——虽然此示例涵盖了正在进行的很多工作,但它绝不是一个完整且准确的 SPA 内部运作示例:因为它取决于
app.js
SPA 的实现方式。更不用说浏览器缓存、页面拆分等因素了。
现在,对于开发和部署过程,事情也变得棘手:
(点击此处查看更高质量的视觉效果)
对于本地开发流程,最有可能处理的是前端和内容交付 server
,以及由所选框架和设置的构建系统。
以防万一我对额外的复杂性不够清楚:已经有一个构建步骤,用于在开发人员编辑的文件和浏览器显示的内容之间建立反馈循环的简单过程。
除此之外,通常还API server
需要额外的信息,以便开发人员可以获取 SPA 的数据。
可能仍在本地设置中,也可能不在。事实上,这有点必要,而且需要维护。
哦,还有更多!由于您使用的是local development server
,因此可能只需要进行一些额外的配置,就能让它们协同工作。很有趣,对吧?
💡 不过,它也有一些优点:
如果您确实将它们两者分开(SPA
对比API
),那么您可以独立部署它们 - 因此,理论上,您应该能够部署更小的功能块。
⚠️ 这里也有一个需要注意的地方:如果您在垂直切片上工作(同时涉及 SPA 和 API),则需要同时部署它们。好消息是,优势仍然适用:首先部署 API 功能,验证一切正常,然后再进行 SPA 更新。这样可以更轻松地进行回滚、实现更精细的部署等等。
总结一下,对于SPA来说:
✅优点server
:代码可重用(由于模板引擎,类似于静态站点生成器),可以提供用户个性化内容,与相比减少了负载server-generated html
,部署规模小,应用程序加载后用户体验良好。
❌缺点local dev env
:需要维护多个构建系统,在和 上都需要进行大量配置prod
,内容无法被网络爬虫索引(爬虫只能看到空白页)
具有服务器端渲染的单页应用程序
SPA本身就很棒static html
。实际上,SPA 就是这么简单,static html
只是增强了而已。既然static html
已经static site generators
解决了它们的缺点,欢迎来到增强版的单页应用——服务器端渲染 SPA。
这是什么意思?我们要把整个SPA都搬上去吗
server
?不完全是 - SSR-SPA 仍然像通常的 SPA 一样利用浏览器,但有一个“小”变化:在第一次请求时,对于简单的 SPA 我们会有一个空的- 现在我们可以从整个中
div
返回。server
HTML
直接的好处是,网络爬虫现在可以索引页面了——而且我们仍然保留着和以前一样的应用程序代码。最重要的是,用户浏览器的解释和运行能力js
不再是信息显示的瓶颈——浏览器html
收到服务器渲染的内容后就可以立即显示。
听起来很棒,让我们把所有SPA 都变成服务端渲染吧?对吧?!
当然,随你便吧。但也请考虑一下成本:对于第一次绘制,服务器需要做一些额外的工作——并处理html
浏览器立即显示的 的生成。
(点击此处查看更高质量的视觉效果)
- Alice
site.com
在浏览器的 URL 栏中输入网址。浏览器(经过一番DNS
操作后)会向服务器发出请求。 - 服务器接收请求、处理请求并返回响应:
html
文件。由于这是第一个绘制请求,服务器将在后台调用 SPA 方法并渲染应向用户显示的完整网页。 - 服务器发回
html
给浏览器进行解释和运行,但也添加了对我们的 SPA 的引用app.js
。 - 浏览器渲染
html
内容——Alice 可以看到她的页面。目前,我们可以将 Alice 浏览器中的内容视为纯粹的static html
。 - 浏览器也开始请求
app.js
文件。它server
会注意到现在请求的是一个静态文件,所以它会直接返回它。 - 浏览器接收并开始处理文件
js
。完成后,我们可以认为文件已从 切换static html
到SPA
。 - Alice 可以像在普通 SPA 中一样与网站进行交互。假设她通过点击按钮执行了某个操作。
8 & 9. 应用程序向服务器发出异步请求;服务器知道SPA 已完全加载(通过请求标头发送的信息)并且它可以采用短路径 - 仅返回“原始”响应,而不将其包装在其中html
。
- 爱丽丝可以看到(几乎是立即的,也许?!)她的手术成功了。
对于 SPA-SSR 的构建和部署,情况更加糟糕:我们必须告别选择自己的服务器端语言的选项。服务器端也有一个硬性的、不可协商的要求:“运行 JavaScript”。向 node.js、bun 和 deno 问好吧。
我们还失去了将 SPA 的静态捆绑包与动态服务器 API 服务器分离的灵活性,因为我们需要将server
和捆绑在一起SPA
。
(点击此处查看更高质量的视觉效果)
总结一下:
✅优点:SPASPA
在功能性、响应性和速度方面都比同类产品更胜一筹(见上文)。
❌缺点:锁定所选的服务器语言;部署规模更大、风险更大;长期维护难度更大。
渐进式 Web 应用
我们已经看到了它们有多么强大
SPA
;SSR-SPA
我们也看到了它们有多么昂贵。
那么渐进式 Web 应用 (PWA) 呢?它们有什么用途?
虽然 PWA 功能强大且灵活,但我更倾向于将其视为“离线 Web 引擎”。借助service worker
,我们现在可以拦截网络请求。
想想看,无论我们目前讨论的是哪种类型的应用,都只有一个共同的需求:从互联网上获取一些文件。如果我们移除这个限制会怎么样?
好吧,我们现在无需互联网就可以访问网络应用程序。
等一下,没有网络吗?
有一个问题——你需要有那个应用程序
installed
。
基本上,如果您正在与 PWA 进行交互,则第一次加载该应用程序时,系统会询问您是否要安装它(理想情况下)。
(点击此处查看更高质量的视觉效果)
虽然它看起来与 SPA 有 99% 相似,但请看一下最后的部分:10 和 11。应用程序注意到它实际上是一个 PWA,而不是一个简单的 SPA。它会询问 Alice 是否同意安装它。12 - Alice 表示同意 - 应用程序service worker
现已注册,并且应用程序已安装。
在安装了应用程序并且没有互联网连接的情况下,如果 Alice 尝试使用相同的应用程序,那么粗略地看一下幕后会发生什么:服务人员会假装他既是 API 又是内容传送服务器。
(点击此处查看更高质量的视觉效果)
对于部署和交付,我们有常用的构建系统,其中我们build
将一些静态文件放入bundle
:
但我们还有一个额外的步骤,一个有趣的细节:部署不再是仅限开发人员的过程。用户可以察觉到这一点。如果应用程序设置为考虑用户的选择,用户甚至可以允许或延迟部署:
我知道大多数人不会同意我的complexity
评分,尤其是在 SSR 与 PWA 的对比上。不过,请听我说完:
-
我认为 PWA 是一种非 SSR-SPA,但具备离线功能。虽然我知道你可以做一个
SSR-PWA
,但我认为它涵盖了多少需求几乎是无法预测的:基本上涵盖了所有需求。但是,它的复杂性分数会飙升。 -
SSR 会把你束缚住,并将前端和后端紧密耦合。我们知道长远来看会怎样。
-
虽然 PWA 的设置和理解很复杂……但一旦你掌握了窍门,并完成了一个可行的设置,它通常就能正常工作了。很多事情都由 Service Worker 自动处理。
-
对于 PWA,你几乎可以随时选择启用或禁用各种设置。唯一危险的是搞乱了
service worker
的自缓存/更新机制。那样你就完蛋了。而 SSR 则是一种非此即彼的设置。
✅优点:具有与普通 SPA 相同的功能 + 在没有互联网连接或间歇性互联网连接时也能工作,并且可以根据需要配置许多额外的功能。
❌缺点:最初设置起来很复杂,需要更周到的方法 - 您的 Web 应用程序现在容易受到“分布式系统谬误”的影响。
WASM
以 的形式交付static html
,带有大量js
用于集成的功能……以及幕后 100,000 个其他功能。
WASM 应用值得更深入地探讨,远不止我在这里的概述。抱歉,我暂时先跳过这部分——我需要对这方面有更深入的了解,才能像对其他类型的应用那样进行总结。
必要的免责声明
这是我的思维模型,它帮助我推理事物。它绝不是Web 应用世界中所有可能性的全面指南。
然而,根据我的经验,理解这些可以帮助我轻松地度过我的工作日,因为我可以扩展我对这些基本概念的知识,然后在此基础上继续发展:
- 出于某种原因,SSR SPA 的某些部分可能具有客户端水化。
- 或者也许我们在构建时部署一个带有来自数据库的评论的静态博客:直到我们重建并重新部署整个网站,新的评论才会显示。
可能性是无穷无尽的。
结束语
❗要使 Web 开发真正有意义,请查看应用程序的整个生命周期,从创建新应用程序所需的时间<div>
,一直到用户(或网络爬虫)如何与您的应用程序交互。
❗ 了解可在浏览器中运行的软件类型之间的所有权衡将带来十倍的回报:现在您几乎可以在所有平台上做任何事情。
❗一旦我能够理解需求,我通常能够将挑战简化为前端/后端问题:用户期望如何与应用程序交互以及应用程序必须支持哪些功能。
❗理解权衡不仅仅意味着“用 React 或 Angular 开发 SPA 或 PWA——哪一个更符合我的需求”。它意味着理解你的应用如何随着时间推移而扩展:开发它的复杂性和成本,以及最重要的……交付它。
Dev.to 社区,如果您已经走到这一步:如果您对该主题有任何反馈,请告诉我,图片和视觉链接是否足够清晰;此外,如果有兴趣,我可以深入探讨某些主题 - 您需要做的就是问 :)
文章来源:https://dev.to/costica/web-apps-my-mental-cheat-sheet-41ah