首页 前端知识 qiankun在主应用、子应用均为vue3 vite typescript中的使用

qiankun在主应用、子应用均为vue3 vite typescript中的使用

2024-05-13 10:05:09 前端知识 前端哥 574 1 我要收藏

介绍

什么是微前端

微前端是一种架构风格,通过将一个单体应用程序拆分成多个小型独立应用程序来实现。每个小型应用程序都专注于一项特定功能,并且可以独立部署、扩展和维护。

为什么需要微前端

  • 复杂性管理

大型单体应用程序随着时间的推移变得越来越复杂,难以维护

  • 团队独立性

微前端允许团队根据其能力和需求独立工作,而不需要干扰其他团队

  • 技术多样性

使用不同的技术堆栈开发各个独立应用程序,而无需考虑整体应用程序的技术选型

核心价值

  • 技术栈无关

主框架不限制接入应用的技术栈,子应用具备完全自主权

  • 独立开发、独立部署

子应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新

  • 独立运行时

独立运行时每个子应用之间状态隔离,运行时状态不共享

优点

  • 可扩展性

通过添加新应用程序来扩展系统而无需修改原始代码

  • 独立部署

每个应用程序都可以独立部署、减少了系统的停机时间

  • 更好的可用性和容错性

由于应用程序之间相互独立,因此如果一个应用程序发生故障,其他应用程序可以继续运行

缺点

  • 导致依赖项冗余,增加用户的流量负担

  • 团队自洽程度的增加,可能会破坏协作

qiankun ——一套完整的微前端解决方案

qiankun能很方便的将一个巨石应用改造成一个基于微前端框架的系统,并且不再需要去关注各种过程中的技术细节,做到真正的开箱即用和生产可用

特点

  • 简单

任意js框架均可使用,微应用接入像使用接入一个iframe系统一样简单,但实际不是iframe

  • 完备

几乎包含所有构建微前端系统时所需的基本能力,如样式隔离、js沙箱、预加载等

  • 生产可用

已在蚂蚁内外经受过足够大量的线上系统的考验及打磨,健壮性值得信赖

使用方法

主应用(vue3+vite+TypeScript)
  1. 创建项目

    npm init vue@latest
    复制
  2. 安装qiankun

    yarn add qiankun
    复制
  3. main.ts注册微应用

    import { registerMicroApps, addGlobalUncaughtErrorHandler, start } from 'qiankun';
    // 注册子应用
    registerMicroApps([
    {
    // 子应用名称,name值必须与子应用vite.config.ts文件中plugins属性qiankun的第一个参数值一致
    name: 'subApp',
    // 默认会加载这个路径下的html,解析里面的js
    entry: '//localhost:5174',
    // 加载的容器(微应用会显示到这个容器里面,一定要保证主应用中有这个容器)
    container: '#subAppContainerVue3', // 和app.vue配置的节点一致
    // 匹配的路由
    activeRule: '/junminronghe', // 访问:http://localhost:5174/juminronghe
    props: {
    mag: '我是主应用main', // 主应用向微应用传递参数
    domain: 'http://localhost:5174',
    },
    }
    // 再有其他子应用,同理
    ]);
    // 启动 qiankun
    start({
    prefetch:'all', // 预加载
    sandbox: {
    experimentalStyleIsolation: true, // 开启沙箱模式,实验性方案
    },
    });
    // 添加全局异常捕获
    addGlobalUncaughtErrorHandler((handler) => {
    console.log("异常捕获", handler);
    });
    复制
  4. app.vue创建挂载节点,如再有其他子应用,也是同理

    <div id="subAppContainerVue3"></div>
    复制
  5. 访问子应用

    <script setup lang="ts">
    import { useRouter } from 'vue-router'
    
    const router = useRouter();
    function goToFunc() {
      router.push('/junminronghe');
    }
    </script>
    
    <template>
      <main>
        <div @click="goToFunc">子应用</div>
      </main>
    </template>
    复制
子应用(vue3+vite+TypeScript)
  1. 安装vite-plugin-qiankunqiankun官方不支持vite)需要安装插件

    yarn add vite-plugin-qiankun
    复制
  2. vite.config.ts

    import { fileURLToPath, URL } from 'node:url'
    import vue from '@vitejs/plugin-vue'
    import qiankun from 'vite-plugin-qiankun'
    export default defineConfig({
    plugins: [
    vue(),
    // qiankun的第一个参数必须与主应用在main.ts中registerMicroApps的name值一致
    qiankun('vue3', {
    useDevMode: true
    })
    ],
    server:{
    headers: {
    'Access-Control-Allow-Origin': '*', // 主应用获取子应用时跨域响应头
    },
    },
    resolve: {
    alias: {
    '@': fileURLToPath(new URL('./src', import.meta.url))
    }
    }
    })
    复制
  3. main.ts

    import { createApp } from 'vue'
    import { renderWithQiankun, qiankunWindow, QiankunProps } from 'vite-plugin-qiankun/dist/helper'
    import App from './App.vue'
    import router from './router'
    const app = createApp(App)
    app.use(router)
    // app.mount('#app')
    // renderWithQiankun: 为子应用导出一些生命周期函数 供主应用在特殊的时机调用
    // qiankunWindow: qiankunWindow.POWERED_BY_QIANKUN 可判断是否在qiankun环境下
    const initQianKun = () => {
    renderWithQiankun({
    // bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap
    // 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等
    bootstrap() {
    console.log('bootstrap');
    },
    // 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法,也可以接受主应用传来的参数
    mount(_props: any) {
    console.log('mount', _props);
    render(_props.container)
    },
    // 应用每次 切出/卸载 会调用的unmount方法,通常在这里我们会卸载微应用的应用实例
    unmount(_props: any) {
    console.log('unmount', _props);
    },
    update: function (props: QiankunProps): void | Promise<void> {
    console.log('update');
    }
    });
    }
    const render = (container) => {
    // 如果是在主应用的环境下就挂载主应用的节点,否则挂载到本地
    const appDom = container ? container : "#app"
    app.mount(appDom)
    }
    // 判断是否为乾坤环境,否则会报错[qiankun]: Target container with #subAppContainerVue3 not existed while subAppVue3 mounting!
    qiankunWindow.__POWERED_BY_QIANKUN__ ? initQianKun() : render(null)
    复制
  4. router——》index.ts

    import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
    import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
    const routes: RouteRecordRaw[] = [
    {
    path: '/',
    name: 'home',
    component: () => import('../views/home/index.vue')
    },
    // 文章详情
    {
    path: '/content',
    name: 'content',
    component: () => import('../views/content/index.vue')
    },
    ];
    const router = createRouter({
    history: createWebHistory(
    // 在乾坤环境下时,将所有的路由地址前加上'/junminronghe',否则将跳转至主应用的相应页面(eg:跳转至这里的文章详情页面,如果不加'/junminronghe'的话,将跳转至主应用的'/content'页面,如果主应用没有这个页面,将跳转至404页面)
    qiankunWindow.__POWERED_BY_QIANKUN__ ? '/junminronghe' : '/'
    ),
    routes
    })
    export default router
    复制

1、子应用的本地资源(图片等)显示404

解决方法:

在子应用的vite.config.ts文件的server对象中配置origin属性,配置为子应用的链接地址

server:{
port: 5174,
// origin:用于定义开发调试阶段生成资产的 origin
// 子应用的地址,用于解决主应用中子应用出现静态地址404问题,控制台报错显示该资源在主应用路劲下
origin: 'http://localhost:5174',
}
复制
2、子应用的接口404

在创建axios实例时,配置baseURL

子应用:

// 创建 axios 实例
const instance = axios.create({
// API 请求的默认前缀
// "/junminrongheApi"要跟主应用,vite.config.ts中,代理的地址一致,给所有的接口请求地址前加“/junminrongheApi"字符串,表明是junminronghe子应用的接口
baseURL: qiankunWindow.__POWERED_BY_QIANKUN__ ? '/junminrongheApi' : '',
timeout: 60 * 1000, //设置超时
headers: {
"Content-Type": "application/json;charset=UTF-8;",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
".AspNetCore.Culture": "c=zh-Hans|uic=zh-Hans",
},
});
复制

主应用:vite.config.ts

export default defineConfig({
plugins: [vue()],
server: {
proxy: {
// "/junminrongheApi"要跟子应用,service——》index.ts中,baseURL的地址一致(即axios的baseURL地址一致),
// 将junminronghe子应用的接口地址代理到其自己的地址(即target与主应用main.ts中registerMicroApps的entry值,保持一致)即可
"/junminrongheApi": {
target: 'http://localhost:5174', // 后台接口
changeOrigin: true,
secure: false, // 如果是https接口,需要配置这个参数
// ws: true, //websocket支持
rewrite: (path) => path.replace(/^\/junminrongheApi/, ""),
},
}
},
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
复制
3、子应用的线上图片地址显示404(一般不会有这个问题)

注:这个是因为这里的图片地址不是常规的地址,而是像这样的地址:sysFileInfo/preview?id=1666025519278534658,所以才会出现这个问题,这个问题是特例,正常的图片地址(eg:https://vitejs.cn/vite3-cn/logo.svg)就不会有这个问题

  • 普通的线上图片加载

解决方法:

在所有的图片地址前,手动拼接一个请求地址,可以封装一个图片组件,统一管理

eg:

<n-image :object-fit="props.objectFit" :src="previewUrl + props.url" />
复制
  • 富文本中的图片加载

富文本中的图片,在加载时,图片地址(sysFileInfo/preview?id=1666025519278534658)前会被拼上主应用的地址及前面配置的子应用路由拼接的'/junminronghe'(目前不知道是为啥)

解决方法:

主应用vite.config.ts

export default defineConfig({
plugins: [vue()],
server: {
proxy: {
// "/junminrongheApi"要跟子应用,service——》index.ts中,baseURL的地址一致(即axios的baseURL地址一致),
// 将junminronghe子应用的接口地址代理到其自己的地址(即target与主应用main.ts中registerMicroApps的entry值,保持一致)即可
"/junminrongheApi": {
target: 'http://localhost:5174', // 后台接口
changeOrigin: true,
secure: false, // 如果是https接口,需要配置这个参数
// ws: true, //websocket支持
rewrite: (path) => path.replace(/^\/junminrongheApi/, ""),
},
// 加这个代理是因为像子应用中如果有富文本,并且富文本中有图片的话,请求的图片会在主应用的地址后面拼上子应用的路由地址(即这里的junminronghe)后再是图片的地址,
// 当然是因为这里的子应用的图片地址不是常规的地址,而是像这样的地址:sysFileInfo/preview?id=1666025519278534658,才会有这样的问题
"/junminronghe": {
target: 'http://localhost:5174', // 后台接口
changeOrigin: true,
secure: false, // 如果是https接口,需要配置这个参数
// ws: true, //websocket支持
rewrite: (path) => path.replace(/^\/junminronghe/, ""),
},
}
},
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
复制
转载请注明出处或者链接地址:https://www.qianduange.cn//article/8489.html
标签
评论
发布的文章

JQuery中的load()、$

2024-05-10 08:05:15

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!