概念和介绍部分这里不做赘述,移步官方文档我觉得是最好的选择https://qiankun.umijs.org/zh/guide
我们这里只讲实现过程和配置。
在gitlab上新建5个项目,分别如下所示:
接下来把以上项目一个个上传到对应的文件目录中
git init
git remote add origin http://10.16.254.60/gia5gu/qiankun-vue1.git
git add .
git commit -m "init"
git push -u origin master
原来的项目结构:
现在单独把.gitignore package.json package-lock.json这三个文件放入到一个单独的文件夹中
并执行:
git init
git submodule add http://10.16.254.60/gia5gu/qiankun-vue1.git(后面这个是各个项目的git clone的地址(包括基座,不包括总控自己本身))
添加完成后目录结构就会多出来一个.gitmodules的文件,表示总控与各个子项目之间建立了关联
接下来让qiankun-demo(总控)去跟git建立关联
git remote add origin http://10.16.254.60/gia5gu/qiankun-demo.git
git add .
git commit -m "初始化项目"
git push -u origin master
至此,我们整个qiankun-demo就整个传上去了。
拉取的时候要记得分配权限哦~
拥有权限的人在拉取代码的时候:
git clone --recurse-submodule <git url>
例:
git clone --recurse-submodule http://10.16.254.60/gia5gu/qiankun-demo.git
这样拉取的是整个微前端项目(里面包含子应用代码)
如果只有git clone <git clone url> 这样拉取的话,子项目只是拉取了一个空文件夹。
场景:
如果非总控管理人员(开发某个子应用的人)去拉取其对应的子项目,就按照普通的
git clone <url> 这样去进行拉取代码进行开发
开发完成后正常提交 push
总控人员想要更新所有子项目(包括基座)上所有的变更,需要用到:
git submodule update --remote → 更新全部子项目
git submodule update --remote <子项目名字>
例:
git submodule update --remote qiankun-vue1
更新完毕后:
就执行常规的 git add . git commit git push 操作,这样总控的代码才会把子项目中的更新也同步更新到。
场景:
假如有两个拥有总控权限的人M1,M2,子项目是A和B两个开发人员,A提交了代码,这时候M1做了更新操作,那么这时候M2拉取总控的代码就是最新的,如果B之后也提交了代码,M1没有做更新,M2这时候拉取总控代码是拿不到B提交的最新代码的。总之,拥有总控权限的人想要获取最新的代码,就需要每次拉取前做更新操作。
我和李鑫觉得这样做的目的在于:可以灵活控制各个子项目版本。比如项目1用1.1版本,项目2用1.2版本
至此,总控和子项目之间的关系就说完了。
下面我们来讲一下部署流程:
前端基座配置:
有两种方案:
第一种是子应用通过nginx反向代理不会引发前端的跨域问题
第二种是子应用通过设置请求头的方式允许跨域
第一种:(推荐)
主应用通过相对路径访问子应用,使用 Nginx 代理
一般这么做是因为不允许主应用跨域访问微应用,做法就是将主应用服务器上一个特殊路径的请求全部转发到微应用的服务器上,即通过代理实现子应用部署在主应用服务器上的效果。
应用配置
主应用
主应用注册微应用时,entry
可以为相对路径,activeRule
不可以和 entry
一样(否则主应用页面刷新就变成微应用):
const apps = [
{
name: 'vueApp1', //应用的名字
entry: '/app1/', //这里对应nginx转发的路径,最后的/一定要加,不加的话会导致部分跳转后的资源无法找到路径
container: '#vueBox',// 挂载子应用到哪个容器上
activeRule: '/vue1', // 激活规则,符合激活规则的话,就把应用挂载到container指定的容器上
},
{
name: 'vueApp2',
entry: '/app2/',
container: '#vueBox',
activeRule: '/vue2',
props: { msg: '我是基座vue2上传来的' }
},
子应用
对于 webpack
构建的微应用,微应用的 webpack
打包的 publicPath
需要配置成 /app1/
,否则微应用的 index.html
能正确请求,但是微应用 index.html
里面的 js/css
路径不会带上 /app1/
。会导致报错We're sorry but ** doesn't work properly without JavaScript enabled. Please enable it to continue.
vue.config.js
module.exports={
publicPath: '/app1/'
}
Nginx配置
主应用 qinakun-base.conf
server {
listen 8080;
server_name localhost;
add_header Cache-Control no-store;
location / {
root /home/qiankun/qiankun-base;
try_files $uri $uri/ /index.html;
index index.html;
}
location /app1/ {
proxy_pass http://192.168.199.130:10000/;
proxy_set_header Cookie $http_cookie;
}
location /app2/ {
proxy_pass http://192.168.199.130:20000/;
proxy_set_header Cookie $http_cookie;
}
location /app3/ {
proxy_pass http://192.168.199.130:30000/;
proxy_set_header Cookie $http_cookie;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
子应用 vue1-10000.conf
server {
listen 10000;
server_name localhost;
root /home/qiankun/vue1-10000;
add_header Cache-Control no-store;
location / {
try_files $uri $uri/ /index.html;
index index.html;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
子应用 vue2-20000.conf
server {
listen 20000;
server_name localhost;
root /home/qiankun/vue2-20000;
add_header Cache-Control no-store;
location / {
try_files $uri $uri/ /index.html;
index index.html;
}
location /app3/ {
proxy_pass http://192.168.199.130:30000/;
proxy_set_header Cookie $http_cookie;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
子应用 vue3-30000.conf
server {
listen 30000;
server_name localhost;
root /home/qiankun/vue3-30000;
add_header Cache-Control no-store;
location / {
try_files $uri $uri/ /index.html;
index index.html;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
配置之后从主应用访问子应用成功,但是单独打开子应用失败报错We're sorry but qiankun-vue1 doesn't work properly without JavaScript enabled. Please enable it to continue.
注意到官方文档中有这样一句话
微应用打包的 publicPath
加上 /app1/
之后,必须部署在 /app1
目录,否则无法独立访问。
尝试修改vue1所在目录名到publicPath中配置的路径名,失败
问题解决:
需要把子应用打包后的文件夹重命名为app1,并放在nginx配置的路径下
子应用目录结构:
$ ll vue1-10000/
total 0
drwxr-xr-x. 4 root root 64 Sep 8 23:00 app1
子应用 vue2-20000.conf
server {
listen 20000;
server_name localhost;
root /home/qiankun/vue2-20000;
add_header Cache-Control no-store;
location / {
try_files $uri $uri/ /index.html;
index index.html;
}
location /app3/ {
proxy_pass http://192.168.199.137:30000/app3/;
proxy_set_header Cookie $http_cookie;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
nginx需要进行如下配置
主应用 qiankun-base.conf
server {
listen 8080;
server_name localhost;
add_header Cache-Control no-store;
location / {
root /home/qiankun/qiankun-base;
try_files $uri $uri/ /index.html;
index index.html;
}
location /app1/ {
proxy_pass http://192.168.199.137:10000/app1/;
proxy_set_header Cookie $http_cookie;
}
location /app2/ {
proxy_pass http://192.168.199.137:20000/app2/;
proxy_set_header Cookie $http_cookie;
}
location /app3/ {
proxy_pass http://192.168.199.137:30000/app3/;
proxy_set_header Cookie $http_cookie;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
这时主应用使用192.168.199.137:8080访问,点击子应用成功
子应用需要通过ip:port/appname 访问
192.168.199.137:10000/app1 成功,点击切换子应用中的路由,成功,刷新报错500
192.168.199.137:20000/app2 主页面成功
192.168.199.137:30000/app3 成功
子应用切换路由之后刷新报错,原因是nginx配置
需要把子应用的nginx配置改为:
vue1-10000.conf
server {
listen 10000;
server_name localhost;
root /home/qiankun/vue1-10000;
add_header Cache-Control no-store;
location / {
try_files $uri $uri/ /app1/index.html; #主要是这里要把index.html的路径配置到app1文件夹下,其他项目都要这么配置
index index.html;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
修改之后测试成功。
第二种方案:主应用使用绝对路径访问子应用
配置微前端,使用nginx发布,主应用中直接配置子应用的ip:port进行跨域访问
使用这种方式时,浏览器访问子应用使用的是子应用的ip地址。所以子应用必须允许跨域
应用配置
const apps = [
{
name: 'vueApp1', //应用的名字
entry: 'http://10.16.254.74:10000', //默认会家在这个html 解析里面的js 动态的执行(自应用必须支持跨域)
container: '#vueBox',// 挂载子应用到哪个容器上
activeRule: '/vue1', // 激活规则,符合激活规则的话,就把应用挂载到container指定的容器上
},
{
name: 'vueApp2',
entry: '//10.16.254.74:20000',
container: '#vueBox',
activeRule: '/vue2',
props: { msg: '我是基座vue2上传来的' }
}
Nginx配置
主应用 qiankun-base.conf
server {
listen 8080;
server_name localhost;
add_header Cache-Control no-store;
location / {
root /home/qiankun/qiankun-base;
try_files $uri $uri/ /index.html;
index index.html;
}
location ^~ /app1/ {
proxy_pass http://192.168.199.130:10000;
proxy_set_header Cookie $http_cookie;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
子应用 vue1-10000.conf
server {
listen 10000;
server_name localhost;
root /home/qiankun/vue1-10000;
add_header Cache-Control no-store;
add_header Access-Control-Allow-Origin * ;
add_header Access-Control-Allow-Methods 'GET,POST,PUT,DELETE' ;
location / {
try_files $uri $uri/ /index.html;
index index.html;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
子应用 vue2-20000.conf
server {
listen 20000;
server_name localhost;
root /home/qiankun/vue2-20000;
add_header Cache-Control no-store;
add_header Access-Control-Allow-Origin * ;
add_header Access-Control-Allow-Methods 'GET,POST,PUT,DELETE' ;
location / {
try_files $uri $uri/ /index.html;
index index.html;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
子应用vue3-30000.conf
server {
listen 30000;
server_name localhost;
root /home/qiankun/vue3-30000;
add_header Cache-Control no-store;
add_header Access-Control-Allow-Origin * ;
add_header Access-Control-Allow-Methods 'GET,POST,PUT,DELETE' ;
location / {
try_files $uri $uri/ /index.html;
index index.html;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}