Skip to content

MicroApp

一款轻量、高效、功能强大的微前端框架

使用

官方文档:https://micro-zoe.github.io/micro-app/docs.html#/zh-cn/start

基座应用

  1. 安装依赖
powershell
npm i @micro-zoe/micro-app --save
  1. 入口文件处引用(通常为 main.js | index.js)
typescript
// 引入 MicroApp
import microApp from '@micro-zoe/micro-app'

// 初始化
microApp.start()
  1. 分配路由
typescript
// router.js
import MyPage from '../views/MyPage/index.vue'
import { createRouter, createWebHistory } from "vue-router";

const routes = [
  {
    // 👇 非严格匹配,/my-page/* 都指向 MyPage 页面
    path: '/my-page/:page*', // vue-router@4.x path的写法为:'/my-page/:page*'
    name: 'my-page',
    component: MyPage,
  },
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

在路由配置的地方,将我们需要使用子应用的组件的路由配置成通用路由的形式。

注意路由的版本。将 path 配置成为通用格式。

  1. 组件中嵌入子应用(案例中则是在 MyPage 中嵌入子应用)
typescript
<micro-app name='app1' url='http://localhost:3000/' baseroute='/my-page'></micro-app>

子应用

  1. 设置基础路由

将基础路由设置成下面的值

typescript
// 👇 设置基础路由,子应用可以通过window.__MICRO_APP_BASE_ROUTE__获取基座下发的baseroute
// 如果没有设置baseroute属性,则此值默认为空字符串
base: window.__MICRO_APP_BASE_ROUTE__ || '/'

如果使用的是 createWebHistory 和 createWebHashHistory 方式创建的路由,base 表示的就是方法的第一个参数。

typescript
createWebHistory(window.__MICRO_APP_BASE_ROUTE__ || '/');

createWebHashHistory(window.__MICRO_APP_BASE_ROUTE__ || '/');
  1. 在 webpack-dev-server 的 headers 中设置跨域支持。
typescript
devServer: {
  headers: {
    'Access-Control-Allow-Origin': '*',
  }
},

特殊点

Vite 构建时

采用 Vite 构建的基座项目和上述用例一致,不需要修改很多地方。

但是,如果子应用使用的是 Vite 构建的项目时,需要进行适配的处理,并且需要舍弃需要 MicroApp 提供的优势。

强烈不建议子应用使用 Vite!

官方文档:https://cangdu.org/micro-app/docs.html#/zh-cn/framework/vite


  1. 子应用 - 添加自定义插件,修改 vite.config.ts 文件
typescript
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { writeFileSync } from 'fs'
import { join } from 'path'

// https://vitejs.dev/config/
export default defineConfig({
  base: `${process.env.NODE_ENV === 'production' ? 'http://my-site.com' : ''}/basename/`,
  plugins: [
    vue(),
    (function () {
      let basePath = ''
      return {
        name: "basename",
        apply: 'build',
        configResolved(config) {
          basePath = `${config.base}${config.build.assetsDir}/`
        },
        writeBundle (options, bundle) {
          for (const chunkName in bundle) {
            if (Object.prototype.hasOwnProperty.call(bundle, chunkName)) {
              const chunk = bundle[chunkName]
              if (chunk.fileName && chunk.fileName.endsWith('.js')) {
                // @ts-ignore
                chunk.code = chunk.code.replace(/(from|import\()(\s*['"])(\.\.?\/)/g, (all, $1, $2, $3) => {
                  return all.replace($3, new URL($3, basePath))
                })
                const fullPath = join(options.dir, chunk.fileName)
                // @ts-ignore
                writeFileSync(fullPath, chunk.code)
              }
            }
          }
        },
      }
    })(),
  ],
  server: {
    port: 3000
  }
})
  1. 子应用 - 修改元素容器 id

因为 vite 子应用没有元素隔离的保护,建议修改容器元素的 id 值,以确保与其它元素不冲突。

修改 index.html,记住同时也要修改挂载时的 id,这个应该不需要过多的说明。

html
<!-- index.html -->
<body><div id="my-vite-app"></div></body>
  1. 子应用 - 调整路由的配置

官方推荐,基座使用 history 路由,使用 Vite 构建的子应用使用 hash 路由。避免出现其他的问题。

子应用如果是 vue3,在初始化时路由时,createWebHashHistory 不要传入参数,如下:

typescript
// router.js
import TestPage from '../views/TestPage/index.vue'
import { createRouter, createWebHashHistory } from "vue-router";

const routes = [
  {
    path: '/',
    redirect: '/test-page'
  },
  {
    path: '/test-page',
    name: 'test-page',
    component: TestPage,
  },
]

const router = createRouter({
  history: createWebHashHistory(),
  routes
})

export default router
  1. 基座应用 - 关闭沙箱并使用内联 script 模式
html
<micro-app
  name='basename'
  url='http://localhost:3000/basename/'
  inline
  disableSandbox
></micro-app>
  1. 基座应用 - 处理子应用静态资源

写一个简易的插件,对开发环境的子应用进行处理,补全静态资源路径。

typescript
microApp.start({
  plugins: {
    modules: {
      // basename即应用的name值
      'basename': [{
        loader(code) {
          if (process.env.NODE_ENV === 'development') {
            // 这里 basename 需要和子应用vite.config.js中base的配置保持一致
            code = code.replace(/(from|import)(\s*['"])(\/basename\/)/g, all => {
              return all.replace('/basename/', 'http://localhost:3000/basename/')
            })
          }

          return code
        }
      }]
    }
  }
})

关于静态文件:

图片等静态资源需要使用绝对地址,可以使用 new URL('../assets/logo.png', import.meta.url).href 等方式获取资源的全链接地址。

有关于通信方式等查询官方文档 -> https://cangdu.org/micro-app/docs.html#/zh-cn/framework/vite

不过看了这么多,不是必要情况下,应该不会去选择使用 Vite 项目作为子应用去使用了吧。

有关于 Vite 的问题:https://github.com/micro-zoe/micro-app/issues/283

小贴士

当使用 webpack 启动 vue 项目时,使用了 vue router 以及 history 模式,本地运行时出现和部署后出现的问题,刷新时直接触发 get 请求,而不是跳转路由,导致出现 404,检查启动指令是否携带 --history-api-fallback 参数。

前端知识体系 · wcrane