前言
关于 前端
和 云计算
的联系,这个话题在我心里已经憋了一段时间了。这个话题有不少可以讨论的地方,包含了整个前端从开发,测试,pipeline到部署,运维的内容。其实我自己也还没整理清楚,所以这篇文章算是先写一个铺垫,尽量讲明白其中的复杂性以及云计算的发展对前端产生的影响。之后有时间再把面临的问题,可行的方案一一阐述和讨论。
下面,我们来聊一聊各自的发展与演进,尽量挑出其中有联系的内容,看看最后云计算是怎样影响到前端发展的。
单机时代
在很久很久以前... 没有云,没有容器,只有简单的 Linux 服务器和简单的 html/css/javascript,前端唯一要做的就是把 index.html
放到服务器的某个文件路径,这个 html 里写明如何导入 js/css,再配置一个类似 Nginx 的网关,把用户的请求路由到该文件,类似下面这样,
NGINX
server {
listen 80;
server_name example.com;
root /path/to/your/web;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
这样基本就可以作为一个静态资源服务了。如果再复杂一点,可以再加一层任何语言写的 web server,经过一次 NGINX 的反向代理,路由到这个 web server 中。
这里为了方便,我们用比较熟悉的 express 为例(注意,要有了 NodeJS 作为服务端之后才能有这玩意),
javascript
const express = require('express');
const app = express();
const path = require('path');
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'index.html'));
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
让 express 起一个 http server,在 3000
这个端口,改一下 Nginx 的配置,
NGINX
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
这样,由于有了一个 Web 服务,前端部署的复杂性稍微提升,通常来说可以结合 server 一起部署。在这种情况下已经算是全栈程序员了吧。
过渡期:关键技术
在前后端分离的浪潮下,计算机科学的各个领域都在蓬勃发展着,数据库兴起 NoSQL 变革,复杂的后端开始"微服务"化,前端也逐渐兴起"微前端"的浪潮。
正如其它领域的创新,至今仍具争议一样,微前端也是颇具争议的话题,一种观点认为它和其它东西一样,只是单纯提高了软件的复杂度,有些卖弄的意味。接下来我们的讨论建立在这种变革的基础之上,毕竟万事万物都在发展变化中,复杂性的提升也带来相应的好处,我在接下来的篇章会尽可能说明这种好处。
微前端
介绍微前端之前,需要介绍一些 Web 应用发展过程中出现的概念。为了把事情讲的简单,这里简单把 Web 应用分为两个时期:
Web 2.0 | Web 2.0+ | |
---|---|---|
概括 | 以整体静态页面展示为主,呈现更多信息需要跳转链接 | 滚动加载信息流,短视频,复杂应用,游戏 |
能力 | / | 1. 页面内刷新 2. 不需要跳转页面就能刷新信息 3. 复杂的交互 4. 流畅的用户体验 |
模式 | MPA(Multi-Page Application),多页应用 | SPA(Single-Page Application),单页应用 |
单个仓库的代码量 | 小 | 巨大 |
开发者维护体验 | 容易 | 困难 |
案例 | 传统的导航网站 | 当下几乎所有应用 |
JavaScript 框架 | JQuery | React/Vue/Angular |
资源打包 | / | Webpack 等 |
包管理 | / | npm |
在传统的页面应用时期,用户体验(UX)其实是很差的,每次切换内容都需要打开新的 tab 或者完全刷新当下的 tab,才能打开新的页面内容。这在当时的互联网发展初期是可以接受的。
随着前端框架与工程化时代的到来,我们可以轻易使用 React 这种框架写出 SPA 应用,保证了流畅的用户体验,可随之而来的问题是,随着需求越来越复杂,代码量越来越大,维护单个前端项目变得困难。开发者(DX)体验越来越差。
问题是,代码拆开后,不同的仓库发布成不同的资源包,用户又需要在不同页面跳转。虽然开发体验提升,可是用户体验又降低了。
微前端要解决的就是这样的问题: 在用户体验(UX)保持流畅的 SPA(单页应用,Single Page Application)的情况下,能够让开发体验(DX)保持 MPA (多页应用,Multiple Page Application)一样容易维护。
具体的微前端方案就不在这里多做讨论了(文末会给一些参考资料)。随之而来的,为了解决微前端的问题,各种 npm 包也被开发出来,比如 single-spa
,qiankun
等,多包管理工具也成为大型 JS 项目的标配,比如 lerna
, nx
,turborepo
等。
说了这么多,这个章节其实是想做一个铺垫。悄然间,前端项目发生了某种重要却又隐蔽的变化:一个代码仓库可以对应多个 Web 应用或者多个 NPM 包了 。这有什么后果呢?简单来说,做前端部署时不能再把产物往服务器上一扔就完事了,你的页面部署方案和微前端产物的管理在某种程度上产生了联系,而前端和云计算的联系就从这里开始了。
更复杂的时,当你在云上有多个集群,多个租户时,要考虑的问题就更多了,以下仅仅是一些例子,
- 低环境和高环境的前端产物有区别时怎么处理?
- 不同环境下产物的依赖关系不同时怎么处理?
- 新开发的需求在低环境测试时怎么部署,有多个不同的需求和代码版本时怎么办?
- 测试环境怎么部署,测试 pipeline 怎么设置?
- 云原生,Kubernetes的容器编排,云厂商的各种服务,产品怎么利用起来?能带来什么好处?
...
问题太多,以后有时间时再深入探讨,正如文章开头所说,这篇文章仅仅是背景介绍和一些铺垫,希望起到抛砖引玉的效果。
虚拟化技术
这个章节可能会对纯前端的同学有些陌生,我尽量用最少的知识,给出最简单的例子。
简单来说,虚拟化技术分为虚拟机和容器化两个方向,我们常说的 Docker 以及 Kubernetes 都是容器化方向的代表,也是目前比较主流的方向。Docker 容器让我们有了在一台机器或虚拟机上隔离并部署多个相同或不同服务的能力,相同的服务可以起到容灾和负载均衡的效果(这种服务发现/负载均衡的能力属于容器编排,也就是需要引入 Kubernetes 这样的工具)。
Docker 是以镜像(Image)作为基本单位的,举例来说,我可以写这样一个Docker文件,
DockerFile
# 使用一个 Linux 版本
FROM alpine:latest
# 安装 NodeJS
RUN apk update && apk add nodejs npm
# 把前端代码仓库拷贝进来
COPY . .
# 执行下载依赖
RUN npm install
# 暴露 3000 端口
EXPOSE 3000
# 执行这个 app.js 文件,它可以是个 express/koa web服务
CMD ["node", "app.js"]
非常简单的一个文件,就可以启动一个 Web Server,省去了很多手动的流程。容器化部署带来的好处是充分的资源利用以及潜在自动化部署的能力(需要搭配更多工具)。有了这个 Web server,用户的请求打到这个服务上时,我们就能返回打包好的前端产物。
对于简单的 Web 服务来说,一个镜像就能搞定部署,这对于一些简单的个人网页或者博客来说非常好用,也非常便宜,这里我们给出一些云厂商提供服务的例子,
云厂商 | 轻量镜像服务 | 轻量 Web 应用服务 | Kubernetes 容器编排服务 |
---|---|---|---|
阿里云 | 无 | 轻量应用服务器 www.aliyun.com/product/swa... | 容器服务 ACK www.aliyun.com/product/kub... |
Amazon Web Service | AWS ECS aws.amazon.com/ecs/ | AWS Lightsail aws.amazon.com/free/comput... | AWS EKS aws.amazon.com/eks/ |
Azure | Microsoft Azure Container Service azure.microsoft.com/en-us/produ... | Azure App Service azure.microsoft.com/en-us/produ... | Azure AKS azure.microsoft.com/en-us/produ... |
表格从左到右是越来越贵的,当然能力也越来越强。这里仅给出一些粗浅的分析,
- 对于简单的个人项目,可以直接部署到轻量镜像服务
- 对于中小企业项目,可以考虑使用轻量应用服务器
- 对于大型项目,可以考虑云厂商提供的 Kubernetes 服务
将前端资源部署到 Kubernetes 有一个好处,因为通常在这种情况下后端服务和前端在同一个集群中,前端访问后端接口的延迟(Latency)会非常小,甚至如果你的数据库或者储存能够在同一地区的云服务中,那么延迟就可以做到非常小了。
Kubernetes 也可以方便地提供不同集群,对应不同的环境,这样自然而然的就有了低环境(测试环境)以及高环境(线上环境),一般来说,前端在低环境部署之后,通过测试 pipeline 后再把产物放到高环境,可以整体提高系统的可用性。当然,这也对前端部署的工程化提出了挑战。
云计算还带来了对象储存(Object Storage)的能力,这可能才是前端上云初期用到最多的能力,因为它最简单,也最符合静态资源储存的直觉,各个云厂商还针对对象储存还提供了各种各样丰富的能力(feature),有机会可以单独开篇说。
CI/CD
CI/CD 其实是属于虚拟化和容器技术的衍生,这里的目的是让前端资源的下列流程自动化和运维化,
- 仓库管理(registry)
- 安装依赖 (install)
- 构建产物 (build)
- 测试(test)
- 发布(deploy)
以及随之而来的各种附加能力。建立这样一个 pipeline 的好处是可以让项目敏捷地迭代,同时保障可用性,少出 bug,就算出现 bug 也能快速地回滚。
一些相关的工具有 Jenkins,GitLab CI,CircleCI 等,一般团队会选择其中一个作为基础。也可以同时引入伴随的产品,比如类似 Nexus Repository 这样的工具来长期储存不同版本的构建产物。
CI/CD 也是前端云化的重要一环,这里面可以引入不同程度的测试流程,来进一步提高可靠性。
结尾
说了这么多,可能有点抽象,其实在掘金这个平台上也经常出现相关的文章或小测,里面或多或少涉及到了一些相关的实践,这里给出一些参考,
后续我会继续整理一些相关的实践,发布一些文章,希望能坚持更新这个系列吧!