关于微前端的思考和MicroApp的初体验

274 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情

前言

随着前端社区的飞速发展,微前端也被提及的越来越频繁,虽然现在很多公司都还没有运用到微前端,但是很多大厂已经将其投入生产了。所以,作为一名前端人员,我们或多或少应该要知道微前端这个东西。

概念

首先呢,微前端它不是一种技术,而是一种架构理念,其实早在2016年就已经有人提出。它的核心在于将单一的web应用拆解成多个可以独立开发、独立运行、独立部署的小型应用,并将他们整合为一个应用。微前端既可以将多个项目融为一个,又可以减少项目之间的耦合,提升项目的可扩展性,相比一整个前端仓库,微前端架构下的前端仓库倾向于更小更灵活。

微前端分为主应用和子应用,主应用也称为基座应用,是其它应用的容器载体,子应用则是被嵌入的一方,并且一个主应用可以包含多个子应用,子应用不受框架和技术限制。如下图所示:

image.png

常见的微前端方案

iframe

iframe应该算是我们前端最早接触的微前端方案,也都用过,相信大家都不陌生。iframe是所有微前端方案中最稳定的、上手难度最低的,但它肯定也有一些问题,比如性能低、通信复杂、有滚动条等,目前觉得iframe只适合简单的页面渲染,不适合做过于复杂的交互逻辑。

npm包管理

我们可以将子应用封装成npm包,通过组件的方式引入,在性能和兼容性上是最优的方案,但有一个问题就是版本更新,每次更新都需要主应用也跟着更新,管理起来可能非常麻烦。

微前端框架

目前市面上流行的微前端框架有single-spa、qiankun、MicroApp,相信大家或多或少都听过。 他们的特点如下:

  • qiankun与single-spa都是通过监听url事件,在路由变化时匹配对应子应用进行渲染。
  • qiankun与single-spa要求子应用修改渲染逻辑并暴露出三个方法:bootstrap、mount、unmount,分别对应初始化、渲染和卸载,这也导致子应用需要对入口文件进行修改。
  • MicroApp借鉴了WebComponent的思想,将微前端封装成一个类WebComponent组件,从而实现微前端的组件化渲染。不需要暴露方法,也不需要修改webpack配置。

我在网上找了一张这三者的对比图

image.png

从上图可以看出,MicroApp的功能可能更加全面,于是乎呢,本人也亲自去实现了一个关于MicroApp的demo,实现起来确实要便捷很多,不需要过多的配置就能实现。demo的github地址我会放在文末。

关于MicroApp

介绍

MicroApp是京东的前端团队开源的一款微前端框架,点击前往官网

它的特点如下:

  • 使用简单:将所有功能都封装到一个类WebComponent组件中,从而实现在主应用中嵌入一行代码即可渲染一个微前端应用。
  • 零依赖:MicroApp没有任何依赖,这赋予它小巧的体积和更高的扩展性。
  • 兼容所有框架:为了保证各个业务之间独立开发、独立部署的能力,MicroApp做了诸多兼容,在任何技术框架中都可以正常运行.

使用指南

以下案例主应用采用vue2+webpack,子应用也采用vue2+webpack。其他框架使用方式大同小异,可进官网查看文档。

作为主应用

强烈建议主应用采用history模式,hash路由的主应用只能加载hash路由的子应用,history模式的主应用对这两种子应用都支持。这里我们默认主应用的路由采用history模式。

  1. 安装依赖
npm i @micro-zoe/micro-app --save
  1. 在入口文件main.js中引入
// main.js
import microApp from '@micro-zoe/micro-app'
microApp.start()
  1. 修改publicPath

这一步借助了webpack的功能,避免子应用的静态资源使用相对地址时加载失败的情况,详情参考webpack文档 publicPath

// vue.config.js
module.exports = {
    publicPath: '/main-vue2/',   // 这里可以根据自己的需求随便定义
    devServer: {
        open: true,   // 运行完成后自动打开浏览器
        port: 8087,   // 修改端口
    }
}
  1. 分配一个路由给子应用
// router.js
import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const routes = [
  {
    // 非严格匹配,/child-vue2/* 都指向 child-vue2 页面
    path: '/child-vue2*',
    name: 'child-vue2',
    component: () => import('../views/child-vue2.vue'),
  },
]

const router = new VueRouter({
  mode:'history',
  base: process.env.BASE_URL,
  routes
})

export default router
  1. 在页面中嵌入子应用
<!--child-vue2.vue-->
<template>
  <div>
    <h1>子应用vue2</h1>
    <!-- 
        name(必传):子应用名称
        url(必传):子应用地址
        baseroute(可选):主应用分配给子应用的基础路由,就是上面的 `/child-vue2`
    -->
    <micro-app 
        name='child-vue2' 
        url='http://localhost:8088/child/vue2/' 
        baseroute='/main-vue2/child-vue2'>
    </micro-app>
  </div>
</template>

作为子应用

  1. 设置跨域支持
// vue.config.js
module.exports = {
  publicPath: '/child/vue2/',               // 这里可以根据自己的需求随便定义
  devServer: {
    port: 8088,                             // 修改端口
    headers: {
      'Access-Control-Allow-Origin': '*',   // 设置跨域
    },
  }
}
  1. 设置基础路由(如果主应用是history路由,子应用是hash路由,这一步可以省略
// router.js
const router = new VueRouter({
  mode: 'history',
  // __MICRO_APP_BASE_ROUTE__ 为micro-app传入的基础路由
  base: window.__MICRO_APP_BASE_ROUTE__ || process.env.BASE_URL,
  routes,
})
  1. 设置publicPath

步骤1: 在子应用src目录下创建名称为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__
}

步骤2: 在子应用入口文件的最顶部引入public-path.js

// main.js
import './public-path'

都配置完成以后,就可以把主应用和子应用跑起来查看效果了。

结尾

以上就是关于MicroApp的简单使用,更多的详细使用教程,请前往MicroApp官网进行查看。

如果大家配置不成功,可以去我的github仓库,查看我写的一个简单的demo ,其中主应用采用了vue2,子应用分别采用了vue2,vue3和react。

最后谢谢大家的观看,如有讲的不对的地方还请指正,谢谢!