前端微服务几种方式:

  1. 使用HTTP服务器(Nginx)的路由来重定向多个应用
  2. 在不同的框架之上设计通讯、加载机制,诸如 Mooa 和 Single-SPA
  3. 通过组合多个独立应用、组件来构建一个单体应用
  4. iFrame,使用 iFrame 及自定义消息传递机制
  5. 使用纯 WebComponent 构建应用
  6. 结合 WebComponent 和 ShadowDOM 来隔离应用

一、 Nginx路由分发

1. 微前端应用目录
/web/root
├── index.html          // 统一入口
├── login.js            // 登录逻辑
│
├── app1                // 应用1
│    ├── index.html
│    ├── favicon.ico
│    └── static
│
└── app2                // 应用2
      ├── index.html
      ├── favicon.ico
      └── static
2. 子应用打包配置
下面以vue配置为例
1.) 路由基路径修改
export default new Router({
    mode: 'history',
    base: '/app1/',
    routes: []
})
2.) 打包路径修改
此路径为打包输出目录
// vue.config.js
outputDir: '/web/root/app1'

// webpack.conf.js
output: {
    path: '/web/root/app1',
}
3.) 发布路径修改
// vue.config.js
publicPath: '/app1/',

// webpack.conf.js
output: {
    publicPath: '/app1/',
}
publicPath配置是index.html引用js的基路径
<script src="/app1/static/js/app.bb9cddb6.js"></script>
3. Nginx路由配置
注意子应用的try_files路径,最后一个是fall back兜底方案
server {
    location / {
        root   /web/root;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
    }

    location /app1/ {
        root   /web/root;
        index  index.html index.htm;
        try_files $uri $uri/ /app1/index.html;
    }
    
    location /app2/ {
        root   /web/root;
        index  index.html index.htm;
        try_files $uri $uri/ /app2/index.html;
    }

    location /app1Api/ {
        proxy_pass http://server1.domain.com/;
    }

    location /app2Api/ {
        proxy_pass  http://server2.domain.com/;
    }
}
再优化一下nginx配置,对所有非/*Api/*请求做正则匹配,获取RegExp.$1(应用的主路径)
    location ~ ^/((\w(?!Api))*)/.* {
        root   /web/root;
        index  index.html index.htm;
        try_files $uri $uri/ /$1/index.html;
    }
location ~ 表示后面是正则表达式,区分大小写;~* 为不区分大小写匹配

二、 Single-SPA

Single-SPA优点:
  1. 兼容各种技术栈:同一页面可使用多种技术框架(React, Vue, AngularJS, Angular, Ember...),且无需刷新页面。
  2. 无需重构现有代码:使用新的技术框架编写代码,现有项目中的代码无需重构。
  3. 更优的性能:每个独立模块的代码可按需加载,不浪费额外资源。
  4. 每个独立模块可独立运行。
1、 源码引用模式

通过single-spa跨端组件将源码直接引用,打包编译成单应用

1.)微服务入口文件:single-spa-config.js
import { registerApplication, start } from 'single-spa'

// 路由模式
let routerMode = 'history'

// 匹配路由规则
let pathPrefix = prefix => {
  if (routerMode === 'hash') {
    return location.hash.startsWith(`#${prefix}`)
  }
  return location.pathname.startsWith(prefix)
}

// 注册应用
registerApplication(
  'react',
  () => import('./src/react/index.js'),
  () => pathPrefix('/react')
)

registerApplication(
  'vue',
  () => import('./src/vue/index.js'),
  () => pathPrefix('/vue')
)

// 启动
start()
2.)react入口文件:src/react/index.js
import React from 'react'
import ReactDOM from 'react-dom'
import singleSpaReact from 'single-spa-react'
import App from './App.js'

const reactLifecycles = singleSpaReact({
  React,
  ReactDOM,
  rootComponent: App,
  domElementGetter: () => document.getElementById('root')
})

export const bootstrap = [reactLifecycles.bootstrap]
export const mount = [reactLifecycles.mount]
export const unmount = [reactLifecycles.unmount]
3.)vue入口文件:src/vue/index.js
import Vue from 'vue'
import singleSpaVue from 'single-spa-vue'
import App from './app.vue'

const vueLifecycles = singleSpaVue({
  Vue,
  appOptions: {
    el: '#root',
    render: r => r(App)
  }
})

export const bootstrap = [vueLifecycles.bootstrap]
export const mount = [vueLifecycles.mount]
export const unmount = [vueLifecycles.unmount]

安静de沉淀
6.5k 声望282 粉丝

忙起来像个狗?,轻松起来像只猫?,没工作闲得像条鱼?