微前端 - 部署配置

470 阅读2分钟

「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战

前言:

以主应用demo-base、子应用1(sub-system)、子应用2(sub-report)为例。

总结,微前端部署配置方法及优缺点。

方法一:一个nginx搞定,配置多个server监听多个端口。

见配置:(nginx.config)

# 主应用
server {
    listen       9000;
    server_name  localhost;

    location / {

        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
        add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';

        root   /usr/local/micro/demo-base/dist/;
        if (!-e $request_filename) {
            rewrite ^(.*)$ /index.html;
        }
    }

    location ~*\.(js|css|png|jpg|jpeg|gif|ico)$ {

        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
        add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';

        root   /usr/local/micro/demo-base/dist/;
        expires 30d;
    }

    location /api/ {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $http_host;
        proxy_pass http://IP:PORT/;
    }

    location /system_api/ {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $http_host;
        proxy_pass http://IP1:PORT1/;
    }
    location /report_api/ {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $http_host;
        proxy_pass http://IP2:PORT2/;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }

}

# 子应用1
server {
    listen       9001;
    server_name  localhost;

    location / {

        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
        add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';

        root   /usr/local/micro/sub-system/dist/;
        if (!-e $request_filename) {
            rewrite ^(.*)$ /index.html;
        }
    }

    location ~*\.(js|css|png|jpg|jpeg|gif|ico)$ {

        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
        add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';

        root   /usr/local/micro/sub-system/dist/;
        expires 30d;
    }

    location /system_api/ {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $http_host;
        proxy_pass http://IP1:PORT1/;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }

}

# 子应用2
server {
    listen       9002;
    server_name  localhost;

    location / {

        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
        add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';

        root   /usr/local/micro/sub-report/dist/;
        if (!-e $request_filename) {
            rewrite ^(.*)$ /index.html;
        }
    }

    location ~*\.(js|css|png|jpg|jpeg|gif|ico)$ {

        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
        add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';

        root   /usr/local/micro/sub-report/dist/;
        expires 30d;
    }

    location /report_api/ {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $http_host;
        proxy_pass http://IP2:PORT2/;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }

}

优点:

配置简单方便

缺点:

无法单独重启单个服务,这样违背了微前端子应用单独部署启动的原则。

方法二:使用docker部署

见配置:

docker容器配置:

version: "3.7"
services:
  chaoan-nginx:
    restart: always
    image: nginx:1.17.8
    container_name: demo-base-nginx
    ports:
      - 9000:80
      - 9001:9001
      - 9002:9002
    privileged: true
    volumes:
      - /etc/localtime:/etc/localtime
      - ./conf/nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./web/dist:/usr/share/nginx/html
      - ../sub-system/web/dist:/usr/share/nginx/sub-system/
      - ../sub-report/web/dist:/usr/share/nginx/sub-report/
      - ./logs:/var/log/nginx

nginx配置:

同方法一中的nginx配置(nginx.config)。

优点:

配置一个docker容器,nginx配置同上,简单方便。

缺点:

同上(无法单独重启单个服务,这样违背了微前端子应用单独部署启动的原则。)

差别:

与上一个方法的差别就在于此方法用到了docker拉取nginx创建镜像进行管理。

方法三:使用docker部署,创建多个docker容器

见配置:

docker容器配置:

version: "3.7"
services:
  demo-base-nginx:
    restart: always
    image: nginx:1.17.8
    container_name: demo-base-nginx
    privileged: true
    ports:
      - 9000:80
    volumes:
      - /etc/localtime:/etc/localtime
      - ./conf/nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./web/dist:/usr/share/nginx/html
      - ./logs:/var/log/nginx
  sub-system-nginx:
    restart: always
    image: nginx:1.17.8
    container_name: sub-system-nginx
    privileged: true
    ports:
      - 9001:80
    volumes:
      - /etc/localtime:/etc/localtime
      - ../sub-system/conf/nginx/nginx.conf:/etc/nginx/nginx.conf
      - ../sub-system/web/dist:/usr/share/nginx/html
      - ../sub-system/logs:/var/log/nginx
  sub-psi-nginx:
    restart: always
    image: nginx:1.17.8
    container_name: sub-report-nginx
    privileged: true
    ports:
      - 9002:80
    volumes:
      - /etc/localtime:/etc/localtime
      - ../sub-report/conf/nginx/nginx.conf:/etc/nginx/nginx.conf
      - ../sub-report/web/dist:/usr/share/nginx/html
      - ../sub-report/logs:/var/log/nginx

nginx配置:(主应用)

server {
    listen      80 ;
    client_max_body_size 5M;

    location / {

        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
        add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';

        root   /usr/share/nginx/html;
        if (!-e $request_filename) {
            rewrite ^(.*)$ /index.html;
        }
    }

    location ~*\.(js|css|png|jpg|jpeg|gif|ico)$ {
        
        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
        add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';

        root   /usr/share/nginx/html;
        expires 30d;
        access_log off;
    }

    location /api/ {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $http_host;
        proxy_pass http://IP:PORT/;
    }

    location /system_api/ {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $http_host;
        proxy_pass http://IP1:PORT1/;
    }
    location /report_api/ {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $http_host;
        proxy_pass http://IP2:PORT2/;
    }

    error_page   500 502 503 504              /index.html;
    location = /index.html {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
}

nginx配置:(子应用1)

server {
    listen       80;
    server_name  localhost;
    client_max_body_size 5M;

    location / {

        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
        add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';

        root   /usr/share/nginx/html;
        if (!-e $request_filename) {
            rewrite ^(.*)$ /index.html;
        }
    }

    location ~*\.(js|css|png|jpg|jpeg|gif|ico)$ {

        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
        add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
        
        root   /usr/share/nginx/html;
        expires 30d;
        access_log off;
    }

    location /system_api/ {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $http_host;
        proxy_pass http://IP1:PORT1/;
    }

    error_page   500 502 503 504              /index.html;
    
}

nginx配置:(子应用2)

server {
    listen       80;
    server_name  localhost;
    client_max_body_size 5M;

    location / {

        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
        add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';

        root   /usr/share/nginx/html;
        if (!-e $request_filename) {
            rewrite ^(.*)$ /index.html;
        }
    }

    location ~*\.(js|css|png|jpg|jpeg|gif|ico)$ {

        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
        add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
        
        root   /usr/share/nginx/html;
        expires 30d;
        access_log off;
    }

    location /report_api/ {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $http_host;
        proxy_pass http://IP2:PORT2/;
    }

    error_page   500 502 503 504              /index.html;
    
}

优点:

可以单独重启docker容器

缺点:

配置相对麻烦,每个nginx单独进行配置,docker配置中需要配置所有的nginx服务映射。

需要注意的是:(跨问题)

主应用、子应用可以单独访问,但是主应用中访问子应用就报错:

Access to fetch at 'http://100.100.110.203:9001/' from origin 'http://100.100.110.203:9000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

因为子应用需要配置跨域!!!

尤其是不要漏了location = /index.html {这个拦截!

  • 1、要不就去掉该拦截直接被location / {拦截
  • 2、要不就都需要加上跨域的代码段:
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';

本文的子应用是去掉了location = /index.html {这个拦截。