Micro-app 微前端框架demo介绍

news2024/9/25 11:20:20

Micro-app 框架

在这里插入图片描述

1、框架安装

npm i @micro-zoe/micro-app --save

2、子应用对应的view页面

<template>
  <div>
    <!-- 
      name(必传):应用名称
      url(必传):应用地址,会被自动补全为http://localhost:3000/index.html
      baseroute(可选):基座应用分配给子应用的基础路由,就是上面的 `/my-page`
     -->
     <micro-app 
      name='app-vue2-demo' 
      url='http://localhost:4001/' 
      baseroute='/app-vue2-demo'
     >
    </micro-app>
  </div>
</template>

3、页面对应的路由

{
      //路由路径最好是非严格匹配
      path: "/app-vue2-demo*",
      name: "Vue2DemoPage",
      component: () => import("@/views/Vue2DemoPage.vue")
}

别忘记,view页面也需要配置

4、子应用的配置

子程序路由需要判断是否加上主程序给予的路由前缀

const router = new VueRouter({
  mode: "history",
  base: window.__MICRO_APP_BASE_ROUTE__ || '/',
  。。。。。
 }

5、子程序需要设置跨域

devServer: {
    port: 4001,
    headers: {
      'Access-Control-Allow-Origin': '*',
    }
}

配置总结

主应用

1、创建一个页面,需要加入micro-app自定义元素

2、配置路由

子应用

1、如果在微前端中,加上路由前缀

2、设置跨域

页面渲染实现原理

其实micro-app原理很简单:WebComponent(Custom Element) + HTMLEntry

其实就是把子应用的资源读取过来,直接在基座程序中运行

与react子应用集成

主应用

1、创建一个页面,需要加入micro-app自定义元素

<micro-app 
      name='app-react-demo' 
      url='http://localhost:4002/' 
      baseroute='/app-react-demo'
>
</micro-app>

2、配置路由

{
      //路由路径最好是非严格匹配
      path: "/app-react-demo*",
      name: "ReactDemoPage",
      component: () => import("@/views/ReactDemoPage.vue")
    }

子应用

1、如果在微前端中,加上路由前缀

<Router basename={window.__MICRO_APP_BASE_ROUTE__ || '/'}>
        <Routes>
          <Route path="/" element={<LayoutMain />} > 
            <Route index element={<Home />} />
            <Route path="about" element={<About />} />
            <Route path="info" element={<Info />} />
          </Route>
        </Routes>
      </Router>

2、设置跨域

headers: {
      'Access-Control-Allow-Origin': '*',
},

3、静态资源的处理

在子应用中的src下创建public-path.js文件

if (window.__MICRO_APP_ENVIRONMENT__) {
  // eslint-disable-next-line
  __webpack_public_path__ = window.__MICRO_APP_PUBLIC_PATH__ //http://localhost:4002  默认/
}

这个文件放入到程序的入口文件index.js中直接执行,建议最好放在第一行

import "./public-path";

与vite项目子应用集成

当子应用是vite应用时需要做特别的适配,适配vite的代价是巨大的,我们必须关闭沙箱功能,因为沙箱在module script下不支持,这导致大部分功能失效,包括:环境变量、样式隔离、元素隔离、资源路径补全、baseroute 等。

在嵌入vite子应用时,micro-app的功能只负责渲染,其它的行为由应用自行决定,这包括如何防止样式、JS变量、元素的冲突。

在module模式下,引入的资源大多为相对地址,兼容主要做的事情就是将地址补全。

vite的module模式是指vite在开发模式下直接使用ES模块来加载代码,而不是像传统的构建工具一样通过打包和压缩,将所有代码打包成一个文件。这种模式让我们开发的时候效率很高,不过却给微前端的集成带来了麻烦

因为我们之前说过micro-app集成的原理,就是把子应用打包好的index.html直接拉过来,然后在基座中运行子应用的代码。vite 这种module模式的话。缺少了这个统一的入口,集成起来就非常的麻烦

1、基座项目中添加页面

views中添加页面ViteDemoPage.vue

<template>
  <div>
    <h2>Main - Vite Vue3 Demo</h2>
    <div>
      <micro-app name='app-vite-demo' url='http://localhost:4003/' baseroute='/app-vite-demo'></micro-app>
    </div>
  </div>
</template>

路由中添加:

{
      path: "/app-vite-demo*",
      name: "AppViteDemo",
      component: () => import("@/views/ViteDemoPage.vue")
 }

app.vue页面别忘记添加路由

2、适配vite项目,子应用修改vite.config.ts文件

无论micro-app框架还是single-spa框架,适配vite项目代价都很大,如果你要集成的项目很多是vite项目,建议直接使用iframe的方式接入,或者使用wujie

这里主要说明两点:

1、path如果报错,需要导入nodejs的TypeScript 的声明文件包 npm i --save-dev @types/node

2、赋值的自定义插件报错,直接any

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path';
import { join } from 'path'
import { writeFileSync } from 'fs'

// https://vitejs.dev/config/
export default defineConfig({
  //域名,生成环境是是你具体的域名,开发环境下为空字符串,这里手动加上了微前端的路由前缀
  base: `${process.env.NODE_ENV === 'production' ? 'http://my-site.com' : ''}/app-vite-demo/`,
  plugins: [
    vue(),
    // 自定义插件
    (function () {
      let basePath = ''
      return {
        name: "vite:micro-app",
        apply: 'build',
        configResolved(config) {
          //配置资源文件基础路径
          //${config.base} 项目基础路径,就是上面配置的那些
          //${config.build.assetsDir}资源文件存放的目录名。默认情况下,它是 'assets'
          basePath = `${config.base}${config.build.assetsDir}/`
        },
        writeBundle (options, bundle) {
          //遍历所有的代码块,找到文件名以 '.js' 结尾的代码块
          for (const chunkName in bundle) {
            if (Object.prototype.hasOwnProperty.call(bundle, chunkName)) {
              const chunk = bundle[chunkName]
              if (chunk.fileName && chunk.fileName.endsWith('.js')) {
               //使用正则表达式来查找所有的相对路径,并使用 new URL() 方法将这些路径转换为绝对路径。
                chunk.code = chunk.code.replace(/(from|import\()(\s*['"])(\.\.?\/)/g, (all, $1, $2, $3) => {
                  return all.replace($3, new URL($3, basePath))
                })
       //options.dir Vite 构建过程中的输出目录,默认情况下,options.dir 的值就是 dist
      //options.dir 是 dist,chunk.fileName 是 main.js,那么完整的文件路径就是 dist/main.js
                const fullPath = join(options.dir, chunk.fileName)
                //将修改后的内容,重新写入文件系统
                writeFileSync(fullPath, chunk.code)
              }
            }
          }
        },
      }
    })() as any,
  ],
  resolve: {
    alias: {
      '@': resolve(__dirname, 'src') // 设置 `@` 指向 `src` 目录
    }
  },
  server: {
    port: 4003,
  }
})
3、子项目修改容器id和渲染容器id
<!-- index.html -->
<body>
  <div id="my-vite-app"></div>
</body>
// main.ts
createApp(App).mount('#my-vite-app')
4、修改路由

vite子项目需要修改为hash路由

由于主应用关闭的沙箱功能,所以基座应用的环境变量不能使用了,所以,每次切换路由的时候就会产生问题

由于hash路由,使用的是地址栏的处理

import { createRouter, createWebHashHistory } from 'vue-router'

const router = createRouter({
  history: createWebHashHistory(),
  routes,
})
5、静态资源
<template>
  <div>
    <div>
      <a href="https://vitejs.dev" target="_blank">
        <img :src="viteLogo" class="logo" alt="Vite logo" />
      </a>
      <a href="https://vuejs.org/" target="_blank">
        <img :src="vueLogo" class="logo vue" alt="Vue logo" />
      </a>
    </div>
    <HelloWorld msg="子应用 -- Vite+Vue@3.x" />
  </div>
</template>

<script setup lang="ts">
import HelloWorld from '@/components/HelloWorld.vue'
const vueLogo = new URL('@/assets/vue.svg', import.meta.url).href
const viteLogo = new URL('/vite.svg', import.meta.url).href
</script>

如果图片比较多,可以用计算属性稍微封装一下

<template>
  <div>
    <div>
      <a href="https://vitejs.dev" target="_blank">
        <img :src="imgUrl('/vite.svg')" class="logo" alt="Vite logo" />
      </a>
      <a href="https://vuejs.org/" target="_blank">
        <img :src="imgUrl('../assets/vue.svg')" class="logo vue" alt="Vue logo" />
      </a>
    </div>
    <HelloWorld msg="子应用 -- Vite+Vue@3.x" />
  </div>
</template>

<script setup lang="ts">
import {computed} from 'vue'
import HelloWorld from '@/components/HelloWorld.vue'
// const vueLogo = new URL('@/assets/vue.svg', import.meta.url).href
// const viteLogo = new URL('/vite.svg', import.meta.url).href

const imgUrl = computed(() => (url: string) => new URL(url, import.meta.url).href);
</script>
6、基座应用的修改,关闭沙箱功能
<micro-app 
  name='app-vite-demo' 
  url='http://localhost:4003/' 
  baseroute='/app-vite-demo'
  inline 
  disableSandbox
 >
 </micro-app>
7、基座应用处理子应用静态资源
microApp.start({
  plugins: {
    modules: {
      // appName即应用的name值,注意这里的name实际上是页面<micro-app>标签的name值
      'app-vite-demo': [{
        loader(code) {
          if (process.env.NODE_ENV === 'development') {
            // 这里 basename 需要和子应用vite.config.js中base的配置保持一致
            code = code.replace(/(from|import)(\s*['"])(\/app-vite-demo\/)/g, all => {
              return all.replace('/app-vite-demo/', 'http://127.0.0.1:4003/app-vite-demo/')
            })
          }
          return code
        }
      }]
    }
  }
})
8、出现的问题

开发者工具console窗口报错

[vite] failed to connect to websocket (SyntaxError: Failed to construct 'WebSocket': The URL 'ws://:/app-vite-demo/' is invalid.)

这个是由于框架自身问题导致,不影响运行,官方已经在1.0beta版本修复了这个问题

由于沙箱隔离关闭,导致环境变量,css隔离,元素隔离、资源路径补全、baseroute等失效

这个问题只有开发者在开发的时候自行定义好开发规范进行规避
demo集合了vue2、vue3、react项目
预览效果
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1364540.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mysql进阶-重构表

目录 1. 原因 2. 如何重构表呢&#xff1f; 2.1 命令1&#xff1a; 2.2 命令2&#xff1a; 2.3 命令3&#xff1a; 1. 原因 正常的业务开发&#xff0c;为什么需要重构表呢&#xff1f; 原因1&#xff1a;某张表存在大量的新增和删除操作&#xff0c;导致表经历过大量的…

Kali Linux——设置中文

【问题现象】 从下图可以看到&#xff0c;菜单全是英文的。对于英文不好的同学&#xff0c;使用起来很难受。 【解决方法】 1、获取root权限 su root 2、进入语言设置 dpkg-reconfigure locales 3、选择zh_CN.UTF-8 UTF-8 4、设置默认 5、安装完成 6、重启虚拟机 reboot…

多租户看这一篇就够了

什么是多租户&#xff1f;举个例子&#xff1a;马云、马化腾和刘强东三个人去租房子&#xff0c;他们因为家里经济困难所以勤工俭学&#xff0c;三个人决定合租一套三室一厅的房子&#xff0c;虽然每个人有自己的房间&#xff0c;但是家里的水电、厨房、卫生间和热水器都是大家…

强化学习的数学原理学习笔记 - 蒙特卡洛方法(Monte Carlo)

文章目录 概览&#xff1a;RL方法分类蒙特卡洛方法&#xff08;Monte Carlo&#xff0c;MC&#xff09;MC BasicMC Exploring Starts&#x1f7e6;MC ε-Greedy 本系列文章介绍强化学习基础知识与经典算法原理&#xff0c;大部分内容来自西湖大学赵世钰老师的强化学习的数学原理…

欧拉函数算法总结

知识概览 欧拉函数为1~n中与n互质的数的个数。假设一个数N分解质因数后的结果为 则欧拉函数 这可以用容斥原理来证明。 欧拉函数的应用 欧拉定理&#xff1a;若a与n互质&#xff0c;则。 费马小定理&#xff1a;欧拉定理中的n为质数p时&#xff0c;可以得到若a与p互质&#xff…

Java:结束本机端口被占用进程

前言 在实际开发当中我们&#xff0c;往往在idea中将某个服务的启动给关闭了&#xff0c;但是在nacos的某个服务上&#xff0c;我们却可以看到本地别名服务还是在上面挂载着本地再次启动的时候就提示【端口被占用】&#xff0c;今天就说一下如何解决这个问题 操作 点击即可预…

我的创作纪念日——redis的历史纪录

机缘 最开始只想存留点Redis的操作信息&#xff0c;后来写着写着也就写多了&#xff0c;虽然后面很长时间由于忙就没继续写&#xff0c;但是还是偶尔登录看一下&#xff0c;有好几篇文章的浏览量还是很多的呢。 收获 收获不多&#xff0c;粉丝也才三十多个&#xff0c;浏览量感…

mac版viso软件 流程图软件omnigraffile

OmniGraffle 是一款由 The Omni Group 开发的绘图工具&#xff0c;主要用于创建各种类型的图表、流程图、组织结构图、网站地图等。它提供了丰富的绘图工具和功能&#xff0c;包括形状、线条、文本、颜色、样式等&#xff0c;可以帮助用户轻松地创建出精美的图表和图形。 OmniG…

优化器(一)torch.optim.SGD-随机梯度下降法

torch.optim.SGD-随机梯度下降法 import torch import torchvision.datasets from torch import nn from torch.utils.data import DataLoaderdataset torchvision.datasets.CIFAR10(root./data, trainFalse, downloadTrue,transformtorchvision.transforms.ToTensor()) data…

【51单片机】独立按键控制LED灯

不同于上篇文章只用代码控制&#xff0c;这次我们要再加上独立按键一同控制LED灯 目录 独立按键控制LED亮灭&#xff1a;代码实现&#xff1a; 独立按键控制LED状态&#xff1a;代码实现&#xff1a; 独立按键实现二进制LED显示&#xff1a;代码实现&#xff1a; 独立按键控制…

【C++】几种常用的类型转换

类型转换 c语言中的类型转换C的类型转换static_castreinterpret_castconst_castdynamic_cast c语言中的类型转换 在C语言中我们经常会遇到类型转化的问题&#xff0c;主要分为两种&#xff1a;显式类型转换和隐式类型转换。 显式类型转换&#xff1a;就是程序员使用强制类型转…

二叉树算法题(一)

根据二叉树创建字符串 根据二叉树创建字符串 给你二叉树的根节点 root &#xff0c;请你采用前序遍历的方式&#xff0c;将二叉树转化为一个由括号和整数组成的字符串&#xff0c;返回构造出的字符串。 空节点使用一对空括号对 "()" 表示&#xff0c;转化后需要省…

SpringBoot全局Controller返回值格式统一处理

一、Controller返回值格式统一 1、WebResult类 在 Controller对外提供服务的时候&#xff0c;我们都需要统一返回值格式。一般定义一个 WebResult类。 统一返回值&#xff08;WebResult类&#xff09;格式如下&#xff1a; {"success": true,"code": 2…

PID各种算法的基本优缺点

PID时间系数对PID本身的影响 积分时间过小积分作用增强。 微分时间过大&#xff0c;微分控制作用过强&#xff0c;容易产生振荡。 在这里的时间系统&#xff0c;一般指的是采样的时间&#xff0c;也就是PID控制的周期。在无人机当中一般采用10ms控制一次。 一般来说采样周期越小…

PMP过了就是中级职称?

&#x1f33b;PMP项目管理专业人士认证在全球范围内受到广泛认可&#xff0c;许多人就误以为获得PMP证书就等同于获得中级职称。但是&#xff0c;事实真的如此吗❓ 1️⃣PMP不属于职称认证 ✅PMP证书&#xff1a; 是由美国项目管理协会(PMI)颁发的专业认证&#xff0c;旨在证明…

GeoServer发布地图服务(WMS、WFS)

文章目录 1. 概述2. 矢量数据源3. 栅格数据源 1. 概述 我们知道将GIS数据大致分成矢量数据和栅格数据&#xff08;地形和三维模型都是兼具矢量和栅格数据的特性&#xff09;。但是如果用来Web环境中&#xff0c;那么使用图片这个栅格形式的数据载体无疑是最为方便的&#xff0…

入库和出库的成本对不上如果如何解决

入库是前期手工录入的车价是对的&#xff0c;出库是根据销售出库单生成的 入库成本和出库成本不一致的解决方法 解决方法&#xff1a; 整车管理——正车库存——库存核算——整车出库 成本核算

FC SAN光纤交换机维护介绍

一、什么是FC SAN &#xff1f; ​存储区域网络&#xff08;Storage Area Network&#xff0c;SAN&#xff09;采用网状通道&#xff08;Fibre Channel &#xff0c;简称FC&#xff0c;区别与Fiber Channel光纤通道&#xff09;技术&#xff0c;通过FC交换机连接存储阵列和服务…

QT上位机开发(会员充值软件)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 所有的控件当中&#xff0c;除了label、edit、radio、combobox和button之外&#xff0c;另外一个用的比较多的控件就是grid&#xff0c;也可称之为…

李沐-《动手学深度学习-02-目标检测

一 、目标检测算法 1. R-CNN a . 算法步骤 使用启发式搜索算法来选择锚框&#xff08;选出多个锚框大小可能不一&#xff0c;需要使用Rol pooling&#xff09;使用预训练好的模型&#xff08;去掉分类层&#xff09;对每个锚框进行特征抽取&#xff08;如VGG,AlexNet…)训练…