微前端之 MicroApp 介绍和基础使用

简介: 微前端之 MicroApp 介绍和基础使用

1. 介绍


MicroApp 是“京东零售”团队在2021年7月正式发布的一个微前端框架,并且抛弃了 Single SPA 的实现理念,基于 CustomElementShadowDom 来实现。


MicroAPP 宣传的优势有以下几点:


  1. 应用接入便捷:主应用只需一行代码即可接入一个微应用(有点夸张哈)


  1. 零依赖:本身 MicroApp 并不依赖其他第三方库


  1. 框架兼容:本身对其他框架应用都做了适配,并且也兼容 Vite 和 Webpack 应用


  1. 其他基本功能:微前端框架都要实现的功能,比如js沙箱、样式隔离、数据通信等


但是因为 MicroApp 依赖 CustomElementproxy,所以浏览器兼容性需要考虑。不过除了已逝的IE,其他浏览器基本都支持。


当然了,因为 MicroApp 发布比较晚,目前也还在 v1 的 alpha 版本,讨论组里面也经常有反馈bug,所以直接上正式项目还有待考虑。


2. 主应用


2.1 路由配置和基础页面


因为 MicroApp 没什么侵入性,所以直接创建用 Vite 创建一个模板项目即可。


npm create vite@latest main-app -- --template vue-ts


📌But: 因为 MicroApp 使用的是 CustomElement,使用的时候与普通 dom 元素一致,在主应用配置路由时最好使用一个空白组件来放置子应用


这样,先创建一个简单的路由配置和对应页面


// router.ts
import { createRouter, createWebHistory } from "vue-router";
const routes = [
  { path: '/', redirect: '/home' },
  { path: '/home/:page*', name: 'home app', component: () => import('@/views/home.vue') },
  { path: '/about/:page*', name: 'about app', component: () => import('@/views/about.vue') },
]
const router = createRouter({
  history: createWebHistory('/'),
  routes: routes,
})
export default router;


// home.vue
<template>
  <micro-app name='home' url='http://localhost:3001/micro-app/home' heep-alive />
</template>
<script lang="ts" setup></script>


// about.vue
<template>
  <micro-app name='about' url='http://localhost:3002/micro-app/about' heep-alive />
</template>
<script lang="ts" setup></script>


🚀 Vue 的路由配置这里需要注意一点:


因为子应用后面通常会有自己的路由,并且不确定是 history 模式还是 hash 模式,所以主应用在配置 path 地址匹配时需要配置 非严格匹配,避免跳转空白页面。


2.2 全局生命周期配置


MicroApp 在主应用注册的时候可以注册全局的生命周期监听函数。


// main.ts
import microApp from '@micro-zoe/micro-app'
const lifeCycles = {
  created() {
    console.log('标签初始化后,加载资源前触发')
  },
  beforemount() {
    console.log('加载资源完成后,开始渲染之前触发')
  },
  mounted() {
    console.log('子应用渲染结束后触发')
  },
  unmount() {
    console.log('子应用卸载时触发')
  },
  error() {
    console.log('子应用渲染出错时触发,只有会导致渲染终止的错误才会触发此生命周期')
  }
}
microApp.start({ lifeCycles })


2.3 主应用插件系统


MicroApp 在主应用启动(调用 microApp.start())时可以在参数中配置应用插件 plugins,并且插件分为 “全局插件 global“ 与 ”子应用插件 modules“。


插件系统的主要作用就是对js进行修改,每一个js文件都会经过插件系统,我们可以对这些js进行拦截和处理,它通常用于修复js中的错误或向子应用注入一些全局变量


一个插件接收以下配置项:


  1. scopeProperties:可选配置,接收 string数组,配置 强隔离的子应用独享全局变量


  1. escapeProperties:可选配置,接收 string数组,效果与 scopeProperties 相反,配置 子应用共享到基座应用和window的全局变量


  1. options:可选配置,接收一个任意类型数据,传递给 loader 配置的函数使用


  1. loader:必须配置,接收一个函数,函数参数为 code, url, options,并且必须将 code 返回


插件配置方式如下:


import microApp from '@micro-zoe/micro-app'
import painfulJoya from '@micro-zoe/plugin-painful-joya' // 官方封装的子午线埋点插件
microApp.start({
  plugins: {
    // 设置为全局插件,作用于所有子应用
    global: [painfulJoya],
    // 设置 home 子应用的独享配置
    home: [{
      scopeProperties: ['AMap'],
      loader(code, url) {
        console.log('我是插件loder函数', code, url)
        return code
      }
    }],
  }
})


3. 子应用


MicroApp 官方在子应用的处理上提供了两种模式:默认模式 和 UMD 模式。


  • 默认模式:该模式不需要修改子应用入口,但是在切换时会按顺序依次执行 所有渲染依赖 的js文件,保证每次渲染的效果是一致的


  • UMD 模式:这个模式需要子应用暴露 mountunmount 方法,只需要首次渲染加载所有 js 文件,后续只执行 mount 渲染 和 unmount 卸载


官方建议频繁切换的应用使用 UMD 模式配置子应用


3.1 Webpack + Vue 子应用


1. webpack 配置


与所有的微前端框架接入子应用一样,首先一样要修改 webpack 的 devServer 配置,来开启跨域请求。


module.exports = {
  devServer: {
    disableHostCheck: true, // 关闭端口检测
    port: 4001,
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  },
  configureWebpack: {
    output: {
      jsonpFunction: `webpackJsonp-chile-vue2`
    }
  },
}


2. 设置 PublicPath


这里可以新建一个 public-path.js 的文件,之后在入口处第一行引入


// __MICRO_APP_ENVIRONMENT__和__MICRO_APP_PUBLIC_PATH__是由micro-app注入的全局变量
if (window.__MICRO_APP_ENVIRONMENT__) {
  // eslint-disable-next-line
  __webpack_public_path__ = window.__MICRO_APP_PUBLIC_PATH__
}
// 之后,在 main.js 中引入


3. 入口文件配置


上文说到了子应用有两种配置方式,主要就体现在入口文件上。


因为路由配置有特殊性,这里先不引用路由,依然是以 Vue 为例


import './public-path'
import Vue from 'vue'
import App from './App.vue'
let app = null
////////// 1. 首先是默认模式的配置
app = new Vue({
  router,
  render: h => h(App),
}).$mount('#app')
// 监听卸载,因为每次都会重新加载所有js,所以建议配置一个卸载方法去清空依赖项等
window.unmount = () => {
  app.$destroy()
  app.$el.innerHTML = ''
  app = null
  console.log('微应用vue2卸载了 -- 默认模式')
}
////////// 2. umd 加载模式
// 初始化与二次加载时调用
window.mount = () => {
  app = new Vue({
    router,
    render: h => h(App),
  }).$mount('#app')
  console.log("微应用vue2渲染了 -- UMD模式")
}
// 卸载操作放入 unmount 函数
window.unmount = () => {
  app.$destroy()
  app.$el.innerHTML = ''
  app = null
  console.log("微应用vue2卸载了 -- UMD模式")
}
// 如果不在微前端环境,则直接执行mount渲染
if (!window.__MICRO_APP_ENVIRONMENT__) {
  window.mount()
}


4. 路由


这里是子应用路由的简单示例


import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter);
const router = new VueRouter({
  mode: 'history', // hash 模式可以不用配置 base
  //  __MICRO_APP_BASE_ROUTE__ 为micro-app传入的基础路由
  base: window.__MICRO_APP_BASE_ROUTE__ || process.env.BASE_URL,
  routes: [
    {
      path: '/',
      name: 'home',
      component: () => import('./pages/home.vue'),
    },
    {
      path: '/page',
      name: 'page',
      component: () => import( './pages/page2.vue')
    }
  ];
})
export default router;


3.2 Webpack + React 子应用


1. 依旧是修改 webpack 配置,开启跨域访问


2. 配置 PublicPath 和入口文件(public-path.js 配置与上面一致)


这里也区分 默认模式 和 umd 模式,默认模式就是将 mount 函数提出来直接运行即可,这里省略


import React from 'react';
import ReactDOM from 'react-dom';
import Router from './router';
window.mount = () => {
  ReactDOM.render(
    <React.StrictMode>
      <Router />
    </React.StrictMode>,
    document.getElementById('root')
  );
}
// 卸载
window.unmount = () => {
  notification.destroy()
  ReactDOM.unmountComponentAtNode(document.getElementById('root'));
}
if (!window.__MICRO_APP_ENVIRONMENT__) {
  window.mount()
}


3. 配置子应用路由


React 的子应用路由配置其实与 Vue 的类似,只是需要配合 ReactRouter 和 jsx 的写法。


import React, { lazy, Suspense, useState, useEffect } from 'react'
import { BrowserRouter, Switch, Route, Redirect, Link } from 'react-router-dom'
function Router () {
  <BrowserRouter basename={window.__MICRO_APP_BASE_ROUTE__ || '/micro-app/react16/'} >
    <Menu mode="horizontal">
      <Menu.Item key='home'>
        <Link to='/'>home</Link>
      </Menu.Item>
      <Menu.Item key='page'>
        <Link to='/page'>page</Link>
      </Menu.Item>
    </Menu>
    <Switch>
      <Route path="/" exact>
        <Home />
      </Route>
      <Route path="/page">
        <Page />
      </Route>
      <Redirect to='/' />
    </Switch>
  </BrowserRouter>
}
export default Router


4. 应用路由配置说明


基础规则:


  1. 主应用是 hash路由,子应用也 必须 是hash路由


  1. 主应用是 history路由,子应用则不受影响


4.1 主应用路由


主应用路由仅控制主应用的页面渲染,与一般单页应用的路由匹配和渲染逻辑一致。


4.2 子应用路由


🚀🚀🚀 主应用使用子应用时,配置的 url 与 baseroute、子应用路由 之间 没有任何关系


子应用与主应用一样是通过 完整的地址栏路由Path(端口号后面的部分) 来进行匹配和渲染的,url 属性仅用于加载子应用 html 文件。


baseroute 属性是用来给子组件使用,以供配置基础路由前缀的,子应用可以通过 window.__MICRO_APP_BASE_ROUTE__ 访问到该属性;并且,子应用使用 hash路由 模式时也 不需要配置 baseroute


根据官方的示例,可以总结以下规则:


  1. url 与路由配置无关,仅作为子应用 html 文件加载地址


  1. 主应用与子应用 共享 地址栏完整的 path路径,但优先级不同:主应用匹配完成之后加载主应用页面,页面中有子应用才渲染子应用并开始子应用路由匹配


  1. 仅当主应用子应用 都使用 history 路由模式,且子应用独立运行时 不需要特定模块前缀 的情况下,主应用使用子应用时需要配置 baseroute 声明模块前缀;并且子应用路由需要配置 base 属性。


目录
相关文章
|
前端开发 JavaScript 安全
微前端之IceStark介绍和基础使用
微前端之IceStark介绍和基础使用
970 1
|
编解码 前端开发 数据处理
前端基础向--从项目入手封装公共组件
前端基础向--从项目入手封装公共组件
302 0
|
Web App开发 存储 JavaScript
开启前端全栈之路—— node 基础
能够和后端程序员更加紧密的配合。 网站业务逻辑前置,学习前端技术需要后端技术支撑(Ajax)。 扩展知识视野,能够站在更高的角度审视整个项目。
142 0
开启前端全栈之路—— node 基础
|
域名解析 网络协议 前端开发
[前端必知 ]HTTP or TCP/IP 基础
[前端必知 ]HTTP or TCP/IP 基础
122 0
|
域名解析 缓存 网络协议
前端基础的几个概念
《基础系列》
138 0
|
JSON 前端开发 JavaScript
Web前端学习:jQuery基础 · 小终结【异步处理AJAX】
Web前端学习:jQuery基础 · 小终结【异步处理AJAX】
123 0
Web前端学习:jQuery基础 · 小终结【异步处理AJAX】
|
前端开发 JavaScript
Web前端学习:jQuery基础--3【jquery操作样式类名、添加元素、jQuery-CSS()方法】
Web前端学习:jQuery基础--3【jquery操作样式类名、添加元素、jQuery-CSS()方法】
174 0
Web前端学习:jQuery基础--3【jquery操作样式类名、添加元素、jQuery-CSS()方法】
|
JavaScript 前端开发
Web前端学习:jQuery基础--2【jQuery事件、设置与获取HTML 】
Web前端学习:jQuery基础--2【jQuery事件、设置与获取HTML 】
128 0
Web前端学习:jQuery基础--2【jQuery事件、设置与获取HTML 】
|
缓存 前端开发 数据可视化
前端基础向--空表格处理与分页调整,优化用户体验
前端基础向--空表格处理与分页调整,优化用户体验
192 0
|
前端开发 算法 数据处理
前端基础向~从项目出手封装工具函数
前端基础向~从项目出手封装工具函数
164 0