微前端配置及部署方案(无界)

1,906 阅读2分钟

前言:

随着技术的不断升级,及新老技术的在项目中的衔接,亦或者是不同技术栈之间的组合,微前端应时而出, 以下是无界微前端配置及部署方案

主工程:

构建脚本配置

import { defineConfig } from 'vite';
const mastername = '主工程产物目录' // 如  master

export default defineConfig({
  build: {
    outDir: `../../dist/${mastername}`
  }
});

hostMap配置:

enum SubDomain {
  MAIN= 'master'
  SUB_1 = 'sub-1',
  SUB_2 = 'sub-2',
}

const isDev = import.meta.env.DEV; // vite 判断是否是本地开发环境

const maps: Record<MainDomain | SubDomain, string> = {
  [Domain.MAIN]: isDev ? '//localhost:9000/' : `//${location.host}/`,
  [SubDomain.SUB_1]: isDev ? '//localhost:9100/' : `//${location.host}/sub-child-1/`,  
  [SubDomain.SUB_2]: isDev ? '//localhost:9200/' : `//${location.host}/sub-child-2/`,
};


此处的 sub-child-1,sub-child-2 与 nginx 中的 location 匹配要一致 并且与 子工程中创建路由时的 base 要一致 并且 与 子工程 vite.config.ts base 值一致

router配置


import { createRouter, createWebHistory } from 'vue-router';
import child1Component from '../views/child1Component.vue';
import child2Component from '../views/child2Component.vue';

const router = createRouter({
  history: createWebHistory('/'),
  routes: [
      {
      path: `/child-1/:path+`,
      name: 'child-1',
      component: child1Component
    },
    {
      path: `/child-2/:path+`,
      name: 'child-2',
      component: child2Component
    },
    {
      path: '/:pathMatch(.*)*',
      name: 'NotFound',
      meta: {
        title: 'NotFound'
      },
      component: Error404
    }]
});

注意:routes 中的 path (child-1 与 hostMap 中的 sub-child-1 不能完全相等, 否则 nginx 配置会出现资源加载异常问题)

子工程

构建脚本如下配置

// vite.config.ts
import { defineConfig } from 'vite';

const subname = '子工程产物目录' // 如  sub1

export default defineConfig({
  base: '/sub-child-1/',
  build: {
    outDir: `../../dist/${subname}`
  }
});


// vue.config.ts
const subname = '子工程产物目录' // 如  sub2
module.exports = {
  publicPath: process.env.NODE_ENV === 'local' ? '/' : '/sub-child-2/',

  // build时构建文件的目录
  outputDir: `../../dist/${subname}`,
}

子项目 base 设置的路径和 Nginx.conf 配置的子项目监听路径不一致页面刷新会报如下错:Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.

router配置

// sub-1
import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router';

const basename = import.meta.env.DEV ? import.meta.env.BASE_URL : '/sub-child-1/';

export function create(routes: Readonly<Array<RouteRecordRaw>>) {
  return createRouter({
    history: createWebHistory(basename),
    routes: []
  });
}

// sub-2
import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router';

const basename = import.meta.env.DEV ? import.meta.env.BASE_URL : '/sub-child-2/';

export function create(routes: Readonly<Array<RouteRecordRaw>>) {
  return createRouter({
    history: createWebHistory(basename),
    routes: []
  });
}

nginx 配置(2 种方案)

第一种方案

server {
  listen 80;
  server_name localhost;
  add_header 'Access-Control-Allow-Origin' *;
  add_header 'Access-Control-Allow-Credentials' 'true';
  add_header 'Access-Control-Allow-Methods' *;
  add_header 'Access-Control-Allow-Headers' *;
    location / {
        root /usr/share/nginx/html/master/;
        index index.html index.htm;
        try_files $uri $uri/ /index.html;
    }

    location /sub-child-1 {
        proxy_pass http://localhost:81/;
    }

    location /sub-child-2 {
        proxy_pass http://localhost:82/;
    }

    location /api/ {
        proxy_pass http://127.0.0.1:3000/;
    }
}

server {
  listen 81;
    location / {
        root /usr/share/nginx/html/sub1/;
        try_files $uri $uri/ /index.html;
        index index.html index.htm;
    }
}

server {
  listen 82;
    location / {
        root /usr/share/nginx/html/sub2/;
        try_files $uri $uri/ /index.html;
        index index.html index.htm;
    }
}

第二种方案

server {
  listen 80;
  server_name localhost;
  add_header 'Access-Control-Allow-Origin' *;
  add_header 'Access-Control-Allow-Credentials' 'true';
  add_header 'Access-Control-Allow-Methods' *;
  add_header 'Access-Control-Allow-Headers' *;
    location / {
        root /usr/share/nginx/html/master/;
        index index.html index.htm;
        try_files $uri $uri/ /index.html;
    }

    location /sub-child-1 {
        alias /usr/share/nginx/html/sub1/;
        try_files $uri $uri/ /sub-child-1/index.html;
        index index.html index.htm;

    }

    location /sub-child-2 {
        alias /usr/share/nginx/html/sub2/;
        try_files $uri $uri/ /sub-child-2/index.html;
        index index.html index.htm;
    }

    location /api/ {
        proxy_pass http://127.0.0.1:3000/;
    }
}

注意: 1、子项 base 设置的路径和 Nginx.conf 配置的子项目监听路径不一致页面刷新会报如下错:Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.

2、主项目 location 的是 root,而子项目中的是 alias

3、子项目 try_files index.html 需要配置前缀路径 /sub

参考资源: mp.weixin.qq.com/s/HwGoXJxOj…