微前端作为解决巨石应用模块化和降低技术框架变动风险的神器,我觉得是当下前端发展的一大方向,可以在未来5-10年内保持生命力。
作者从2019年12月第一次使用qiankun框架落地微服务以来已经过去了一年多的时间,形成了、脚手架、工程结构设计、日常开发维护、性能优化、部署等一整套流程。
之前有两篇文章讲了qiankun的入门文章:
qiankun微前端实战看这篇就够了 - Vue项目篇:这篇文章编写的较早,大致在19年12月份当时qiankun还在1.x版本,现在关于微应用注册及应用间通信的部分已经和现版本不再合适,因此不再建议刚接触qiankun的同学阅读了
vue3.0&qiankun2.0极速尝鲜,微前端进阶实战!:这篇是基于qiankun2.0的入门文章,以及如何将1.0平滑升级至2.0版本,另外也探讨了主应用+n子应用的双端口配置方案
下面讲讲作者在部署上做的一系列方案探索(以下两种方案都更适合一个团队维护N个微应用的场景):
1 脚本部署
2 docker部署
- 每个模块一个镜像【X】
- 只使用一个nginx镜像,将前端代码和nginx配置全部通过挂载的方式引入【X】
- 只使用一个nginx镜像,将前端代码copy至镜像内部,只将nginx配置挂载【√】
- 每个模块一个镜像,主应用镜像使用挂载nginx配置保证灵活性;再配合脚本解决多镜像维护繁琐的缺点【√】
- 有条件可以oss
脚本部署
脚本部署是指使用npm run xx的形式一个命令即可将前端静态资源推送至服务器的方式
大致思路:
- 使用node+inquirer编写交互式命令行脚本,像vueCli创建项目一样以伪可视化的形式一步一步指引使用人员进行部署操作。
- 通过ssh2-sftp-client插件将读node取到的本地文件上传至linux服务器。
- 将脚本启动命令文件改成.bat文件,可以实现在自己电脑上双击运行。
功能有:
- 使用node读写服务器配置文件,可通过交互式命令行以input框输入的形式创建新的服务器信息
- 通过交互式命令行以选择的形式,将前端打包好的文件按你所选要求部署至所选服务器
效果如下:
添加目标服务器信息
一键部署
缺点
- 需要在目标服务器上配好nginx服务及开机运行(无法带运行环境一起部署)
- 暂时无法向windows系统推送部署
- node读取文件路径虽然可配,但既然要配肯定需要知道微应用打包好的文件位置
- 需要知道服务器root或者有足够高权限的账号密码
其中node读写、inquirer命令行交互插件、ssh2-sftp-client将文件推送到服务器都是很成熟的插件,另外多个项目一键下载依赖、一键打包、一键部署脚本地址:多个微应用操作脚本,此外还可以继续优化,将拉取代码、打包、部署做到一起去,更适合非程序人员。
docker 部署
作者刚接触docker几天时间,如有不对之处,欢迎斧;更欢迎指点更多巧妙姿势。
既然是多个微应用,那直接来docker-compose吧。官方简介是这么介绍compose的:负责实现对 Docker 容器集群的快速编排
。
按docker文档将docker及docker-compose等相关配置都做好:(win版docker自带docker-compose,开启镜像加速即可;contos需要设置docker用户组、镜像加速、单独安装docker-compose等,都按上面官方简介文档操作即可)
docker自带前端运行环境,无需再面对在我这好好的在他那那会不能跑呢的尴尬局面
使用docker-compose将每个微应用都打包成一个镜像部署
此方案每次微应用内容变更或nginx配置变更之后都需要重新打包镜像,非常繁琐,即便是在docker内npm run build打包并将dist COPY 至镜像空间也依旧如此,且无法保证git pull的代码是功能完整且无错的
缺点
- 某一镜像下内容或nginx配置变动,需要重新生成此应用的镜像
此方案推荐指数:**
步骤
- 在项目根目录添加
docker-compose.yml
文件。通过docker-compose去调度每个子应用和node服务里面的Dockerfile
services:
# 服务端配置
wl-mfe.server:
container_name: wl-mfe.server
restart: always
build:
context: ./_server
dockerfile: Dockerfile
ports:
- '3700:3700'
# 主应用配置
master: # docker-compose内的容器名
container_name: master # 容器名
restart: always # 重启策略: 容器退出时总是重启容器
build:
context: ./master # 服务指定上下文目录
dockerfile: Dockerfile # 相对于context的dockerfile文件路径
environment:
NODE_ENV: 'production'
ports:
- '2750:2750' # 端口映射,宿主机端口:容器端口
# subapp-login配置
login:
container_name: subapp-login
restart: always
build:
context: ./subapp-login
dockerfile: Dockerfile
environment:
NODE_ENV: 'production'
ports:
- '2753:2753'
depends_on: # 依赖容器名,会在此容器启动之后启动
- master
# ...其他子应用配置方法如上
- 根据docker-compose.yml的build路径,在每个子应用文件夹下添加
Dockerfile
和对应的nginx配置文件yourname.conf
。
Dockerfile文件,注意里面路径即可;另外注意在每个应用目录添加.dockerignore文件,忽略下node_modules
# 从官方拉取nginx镜像
FROM nginx
# 复制dist文件夹到镜像空间,注意docker-compose.yml中指定master的build从./master文件夹开始
COPY dist/ /usr/local/web/master/
# 复制master.conf到镜像空间
COPY master.conf /etc/nginx/conf.d/master.conf
master.conf文件,这里nginx配置和普通无二,主应用比子应用多了接口代理,少了允许跨域头信息,其他一致。
server {
listen 2750;
server_name 127.0.0.1;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root /usr/local/future/web/master;
index index.html index.htm;
try_files $uri $uri/ /index.html;
# 普通模块接口地址
location ^~ /Api/ {
proxy_pass $host:3700/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
#由于服务器端源码(建议大家做好大小写匹配)只匹配了"Upgrade"字符串,所以如果这里填"upgrade"服务器端会将这条http请求当成普通的请求,导致websocket握手失败
proxy_set_header Connection "Upgrade";
proxy_set_header Remote_addr $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 600s;
}
# 解决 nginx 禁止post请求问题,需要后台配置跨域
error_page 405 =200 http://$host$request_uri;
}
error_page 502 503 504 /50x.html;
location = /50x.html {
root /usr/local/future/web/master;
}
}
- 运行
docker-compose up -d
打包并启动镜像或docker-compose build
打包镜像,上传阿里云或其他私有镜像中心即可
启动成功后可以在终端看到容器信息。
代码地址:Github & node服务Dockerfile & 主应用Dockerfile & 子应用Dockerfile
使用docker-compose打包一个nginx镜像,并将所有微应用通过数据卷的方式挂载进来
此方案除了node服务端外,将所有web端微应用挂载到nginx镜像下,其原理和正常一个nginx启动全部前端静态资源服务一样。这样部署的时候即带nginx环境一起部署,也不需要维护过多的镜像资源,只把所有微应用打包好的dist目录通过volumes挂载至nginx镜像即可。
优点
- 因为是挂载的方式,微应用的内容变更或者nginx的配置变更都无需重新制作镜像,只需要重启容器即可生效!
- 使用nginx官方镜像即可,无需推送至阿里云再拉取部署
缺点
- 也因为是挂载的方式,需要在宿主机上存在全部应用的dist文件,运维除了关注镜像还需关注代码
此方案推荐指数:**
步骤
- 在项目根目录添加
docker-compose.yml
文件。
# by weilan in 2020.01.25
version: '3'
services:
# 服务端配置
wl-mfe.server:
container_name: wl-mfe.server
restart: always
build:
context: ./_server
dockerfile: Dockerfile
ports:
- '3700:3700'
wl-mfe.web:
image: nginx
restart: always
container_name: nginx
environment:
- TZ=Asia/Shanghai
ports:
# nginx端口与宿主机端口映射
- "8080:80"
- "80:80"
- "443:443"
# 下面是各个微前端的端口映射
- "2750:2750"
- "2751:2751"
- "2752:2752"
- "2753:2753"
volumes:
# 挂载nginx配置
- ./_docker/nginx/default.conf:/etc/nginx/nginx.conf
# 挂载各个微前端静态资源
- ./master/dist/:/usr/local/web/master/
- ./subapp-blog/dist/:/usr/local/web/subapp-blog/
- ./subapp-login/dist/:/usr/local/web/subapp-login/
- ./subapp-ui/dist/:/usr/local/web/subapp-ui/
- 运行
docker-compose up -d
打包并启动镜像或docker-compose build
打包镜像,上传阿里云或其他私有镜像中心即可
只使用一个nginx镜像,将前端代码copy至镜像内部,只将nginx配置挂载
此方案解决了运维除了关注镜像还得关注代码的问题,并且所有前端模块都打包进一个镜像内部,降低运维门槛
优点
- 一个镜像完成微前端n个模块的部署,简单粗暴
- 有些公司没运维或被抓去顶岗型的运维,降低门槛节省认知成本
- nginx挂载是因为nginx会有修改的需求,但只重启容器即可
缺点
- 因为全部在一个镜像,一个模块改动重启的是整个项目
- 微前端有个特性就是独立部署,这下又一窝端了
此方案推荐指数 **
步骤
- 在项目根目录添加
docker-compose.yml
文件
# by weilan in 2020.02.22
version: '3'
services:
# 服务端配置
wl-mfe.server:
container_name: wl-mfe.server
restart: always
build:
context: ./_server
dockerfile: Dockerfile
ports:
- '3700:3700'
wl-mfe.web:
image: nginx
restart: always
container_name: nginx
build: .
environment:
- TZ=Asia/Shanghai
ports:
# 下面是各个微前端的端口映射
- "2750:2750"
- "2751:2751"
- "2752:2752"
- "2753:2753"
volumes:
# 挂载nginx配置
- ./_docker/nginx/default.conf:/etc/nginx/nginx.conf
- 在根目录增加Dockerfile文件
FROM nginx
COPY master/dist/ /usr/local/future/web/master/
COPY subapp-login/dist/ /usr/local/web/subapp-login/
COPY subapp-ui/dist/ /usr/local/web/subapp-ui/
COPY subapp-blog/dist/ /usr/local/web/subapp-blog/
注意Dockerfile文件平级添加.dockerignore忽略一下依赖目录
- 运行
docker-compose up -d
打包并启动镜像或docker-compose build
打包镜像,上传阿里云或其他私有镜像中心即可
每个模块打包成一个镜像,主应用nginx配置挂载,其他子应用nginx配置打包进镜像内部,并配合脚本做打包上传
此方案和docker部署方案1大致相同,只是把主应用将nginx配置copy至镜像内部改为数据卷挂载的方式,因此日常调整nginx只重启容器即可
优点
- 符合微前端独立部署的风格
- 无需关注代码层,只维护镜像
- 配合脚本解决多镜像维护操作繁琐的问题
缺点
- 模块多镜像确实多,而且后续肯定还需要增加模块,需要设计一个好的部署管理方案
步骤
- 在项目根目录添加
docker-compose.yml
文件。和docker部署方案1相同,但是在master应用下增加数据卷挂载nginx
services:
# 服务端配置
wl-mfe.server:
container_name: wl-mfe.server
restart: always
build:
context: ./_server
dockerfile: Dockerfile
ports:
- '3700:3700'
# 主应用配置
master: # docker-compose内的容器名
container_name: master # 容器名
restart: always # 重启策略: 容器退出时总是重启容器
build:
context: ./master # 服务指定上下文目录
dockerfile: Dockerfile # 相对于context的dockerfile文件路径
environment:
NODE_ENV: 'production'
ports:
- '2750:2750' # 端口映射,宿主机端口:容器端口
volumes:
# 挂载nginx配置
- ./nginx.conf:/etc/nginx/nginx.conf
# subapp-login配置
login:
container_name: subapp-login
restart: always
build:
context: ./subapp-login
dockerfile: Dockerfile
environment:
NODE_ENV: 'production'
ports:
- '2753:2753'
depends_on: # 依赖容器名,会在此容器启动之后启动
- master
# ...其他子应用配置方法如上
- 根据docker-compose.yml的build路径,在每个子应用文件夹下添加
Dockerfile
和对应的nginx配置文件yourname.conf
。
这一步只有master项目下有修改,因为在docker-compose中的master挂载了nginx配置,master的Dockerfile中需要将COPY nginx配置
的命令去掉
- 运行
docker-compose up -d
打包并启动镜像或docker-compose build
打包镜像,上传阿里云或其他私有镜像中心即可 - 编写脚本帮助我们一键处理n个镜像的打包上传操作
因篇幅过长,docker打包与上传脚本另起一篇文章说明
CICD
目前使用jenkins,社区内教程非常之多,docker的教程也不少,后续研究完补上。
如果有微前端项目工程优化需求,作者可以另开一篇文章介绍
![上传失败,undefined]()
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。