Micro-app vue3+vite+ts用法

news2024/10/7 12:27:40

前言:

微前端的概念是由ThoughtWorks在2016年提出的,它借鉴了微服务的架构理念,核心在于将一个庞大的前端应用拆分成多个独立灵活的小型应用,每个应用都可以独立开发、独立运行、独立部署,再将这些小型应用融合为一个完整的应用,或者将原本运行已久、没有关联的几个应用融合为一个应用。微前端既可以将多个项目融合为一,又可以减少项目之间的耦合,提升项目扩展性,相比一整块的前端仓库,微前端架构下的前端仓库倾向于更小更灵活。

它主要解决了两个问题:

  • 1、随着项目迭代应用越来越庞大,难以维护。
  • 2、跨团队或跨部门协作开发项目导致效率低下的问题

 基于vite的实现:

首先创建一个主应用和一个子应用

yarn add @vitejs/app microapp_tool --template vue-ts

npm init @vitejs/app microapp_tool --template vue-ts

这是一个主应用

 

yarn add @vitejs/app spoon_tool --template vue-ts

npm init @vitejs/app spoon_tool --template vue-ts

这是一个子应用

 子应用:

router/index.ts


/**
 * @param  {Function}   ...
 */

import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
import cubetoolPath from "./modules/cube"

const routes: RouteRecordRaw[] = [
    { path: "/ceshi", name: "ceshi", component: () => import("@/views/output/ceshi.vue") },
    { path: '/host', name: "host", component: () => import("@/components/spoon/handsontable.vue") },
    { path: '/table', name: "table", component: () => import("@/components/spoon/EditableProTable.vue") },
    {
        path: '/cube', name: 'cube', component: () => import('@/views/output/cube.vue'),
        children: [...cubetoolPath]
    },
    {path:"/",redirect:"/cube"}
]

const options = {
    // 👇 设置基础路由,子应用可以通过window.__MICRO_APP_BASE_ROUTE__获取基座下发的baseroute,如果没有设置baseroute属性,则此值默认为空字符串
    history: createWebHashHistory(),
    routes,
}

const router = createRouter(options)

export default router


这里要注意的是:路由模式要用hash模式  即:history: createWebHashHistory()

vite.config.ts

import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
//import hook reactive ref....
import AutoImport from "unplugin-auto-import/vite"
//import  ele-plus....
import Components from "unplugin-vue-components/vite"
//elementplus
import { ElementPlusResolver } from "unplugin-vue-components/resolvers"
//es6-modules 语法解析
import path from 'path'
import { resolve, join } from "path"
import { writeFileSync } from "fs"

export default (({ mode }) => {
  //检查process.cwd()路径下.env.development....
  loadEnv(mode, process.cwd())

  const { VITE_APP_BASE_API, VITE_BASE_API, VITE_ENV } = loadEnv(mode, process.cwd());


  // https://vitejs.dev/config/
  return defineConfig({
    base: `${VITE_ENV === 'production' ? 'http://my-site.com' : ''}/spoon_tool/`,//baseName 主应用所需
    plugins: [
      vue(),
      //ele 按需导入
      AutoImport({
        //ref 、reactive.....
        imports: ['vue', 'vue-router'],
        dts: "src/auto-imports.d.ts",
        // ele-plus
        resolvers: [ElementPlusResolver()]
      }),
      Components({
        // ele..
        resolvers: [ElementPlusResolver()]
      }),
      // 自定义插件  micro-app微前端 子应用 配置
      (function () {
        let basePath = ''
        return {
          name: "vite:micro-app",
          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')) {
                  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)
                  writeFileSync(fullPath, chunk.code)
                }
              }
            }
          },
        }
      })(),
    ],
    resolve: {
      alias: {
        "@": resolve(__dirname, "src"),
        "@assets": resolve(__dirname, "src/assets"),
        "@store": resolve(__dirname, "src/store"),
        "@views": resolve(__dirname, "src/views")
      }
    },
    css: {
      preprocessorOptions: {
        less: {
          modifyVars: {
            hack: `true; @import (reference) "${path.resolve("src/assets/css/base.less")}";`,
          },
          javascriptEnabled: true,
        },
      },
    },
    server: {
      // port: 3000,
      // proxy: {
      //   [VITE_BASE_API]: {
      //     target: VITE_APP_BASE_API, // 实际请求地址
      //     changeOrigin: true,
      //     rewrite: (path) => path.replace(/^\/api/, ""),
      //   },
      // },
      port: 8081,//主应用所挂载的url端口
      headers: {
        'Access-Control-Allow-Origin': '*',//子应用必须开启跨域,否则无法访问
      }
    },
  })
})


这里主要注意的是跨域处理、端口号定义、自定义插件的应用

index.html

 <div id="my_vite_app"></div>

模板ID的修改,这里是为了不与主应用ID发生冲突,

当然,对应的main.ts也得保持一致

app.mount('#my_vite_app')

主应用:

yarn add @micro-zoe/micro-app

router/index.ts


/**
 * @param  {Function}   ...
 */

import { createRouter,createWebHistory, Router, RouteRecordRaw } from 'vue-router'
import MyPage from '../views/spoon_tool.vue'

const routes: RouteRecordRaw[] = [
    {
        //严格模式
        path: "/spoon_tool/:page*",
        name: "spoon_tool",
        component: MyPage
    }
]

const options = {
    // 👇 设置基础路由,子应用可以通过window.__MICRO_APP_BASE_ROUTE__获取基座下发的baseroute,如果没有设置baseroute属性,则此值默认为空字符串
    history: createWebHistory(),
    // base: process.env.BASE_URL,
    routes,
}

const router: Router = createRouter(options)

export default router


这里要注意的是所需的path为子应用的baseName值,其路由模式要为history模式

views/spoon_tool.vue

<!-- my-page.vue -->
<template>
    <div class="base">
        <!-- 
        name(必传):应用名称
        url(必传):应用地址,会被自动补全为http://localhost:3000/index.html
        baseroute(可选):基座应用分配给子应用的基础路由,就是上面的 `/my-page`
       -->
        <micro-app class="micro-app" disableScopecss disableSandbox inline style="height: 100%;" name='spoon_tool' url='http://localhost:8081/spoon_tool/#/cube' baseroute='/my-page'></micro-app>
    </div>
</template>
  <style lang="less" scoped>
    .base{
        width: 100%;
        height: 100%;
        // background: red;
        display: flex;
        flex-direction: column;
        h1{
            background: pink;

        }
        .micro-app{
            flex: 1;
        }
    }
  </style>

这里的micro-app标签中对应子应用的url

main.ts

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from "./router/index"
// import "./public-path"
import ElementPlus from "element-plus"
import "element-plus/theme-chalk/index.css"

// 鼠标右键
import contextmenu from "v-contextmenu";
import "v-contextmenu/dist/themes/default.css";

//ele icon
import * as ElementPlusIconsVue from '@element-plus/icons-vue'

//pinia
import pinia from "./store/index"

//i18n多语言配置
import i18n from "./lang/index"

//sql
// import Codemirror from "codemirror-editor-vue3"
// import Codemirror from "codemirror-editor-vue3";

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

/**
 * @params 解决Chrome报错 Added non-passive event listener to a scroll-blocking <some> event. Consider marking event handler as ‘passive’ to make the page more responsive. See <URL>
 * @Desc 通过添加 passive,来阻止 touchstart 事件 提高滚动性能和防止滚动阻塞
 */
// import "default-passive-events"

const app = createApp(App)

//导入所有图标进行全局注册
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
    app.component(key, component)
}


app.use(router)
app.use(ElementPlus)
app.use(pinia)
app.use(i18n)
app.use(contextmenu)
// app.use(Codemirror)
app.mount('#app')

// 监听卸载操作
window.addEventListener('unmount', function () {
    app.unmount()
})

microApp 的引入与使用

效果:

 

 

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

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

相关文章

文库小程序在线阅读下载文档模板流量主小程序

一、什么是文库小程序&#xff1f; 文库小程序连接流量主&#xff0c;具体流程是粉丝进入小程序下载文档模板&#xff0c;下载前需要看广告&#xff0c;阅读后可以免费下载文档模板。具体的小程序演示请参见抖音云云文库 二、文库小程序的应用范围 小程序主要实现文档共享功能…

Redis Linux安装

Redis版本下载,版本地址http://download.redis.io/releases/ 点击跳转 新建文件夹 mkdir /usr/local/redis 上传压缩包,并使用命令解压tar -zxvf redis-6.2.8.tar.gz (redis-6.2.8.tar.gz为安装包) 安装依赖 yum install gcc-c 编译 make 安装 make install 修改配置 …

概率论和随机过程的学习和整理20:条件概率我知道,但什么是条件期望?可用来解决递归问题

目录 1 目标问题&#xff1a; 什么是条件期望&#xff1f; 条件期望有什么用&#xff1f; 2 条件期望&#xff0c;全期望公式 3 条件期望&#xff0c;全期望公式 和 条件概率&#xff0c;全概率公式的区别和联系 3.1 公式如下 3.2 区别和联系 3.3 概率和随机过程 4 有什…

Zabbix“专家坐诊”第200期问答汇总

问题一 Q&#xff1a;想请问下大佬们&#xff0c;我们zabbix最近有误告警的情况&#xff0c;这个怎么排查呢&#xff1f; 用了proxy&#xff0c;我看了proxy和server的日志&#xff0c;除了有慢查的日志&#xff0c;其它没有异常日志输出。 A&#xff1a;看下这个unreachable的…

首次与电商平台战略签约 第一三共与阿里健康达成战略合作

7月18日&#xff0c;阿里健康与第一三共在杭州正式签署战略合作协议。双方宣布将在此前合作基础上&#xff0c;全面深化心脑血管、风湿骨外科等疾病领域的合作深度&#xff0c;探索以患者为中心、以数字化为驱动力的创新型医药健康服务模式。据悉&#xff0c;此次合作是第一三共…

椒图--分析中心和后台管理中心

护网的时候我们要把右边的开关开启。开启就会对系统全量的记录&#xff0c;包含有网络行为日志&#xff0c;就会检测我们服务器里面的链接&#xff0c;端口箭头&#xff0c;内内网暴露的链接&#xff1b;进程操作日志&#xff0c;就可以看我们系统创建了哪些进程&#xff0c;就…

融云出海:不止假发出口和四卡四待手机,「非洲市场」的参差与机遇

↑ 点击预约“融云北极星”直播↑ 点击预约“实时社区”直播 比白皮书更精炼省流&#xff0c;比图谱更实用有效。 融云《社交泛娱乐出海作战地图》&#xff0c;被多位大咖标记为出海人必备工作手册。针对地图的核心模块&#xff0c;我们推出了系列解读文章&#xff0c;更详尽…

Redis数据持久化的两种方式

说明&#xff1a;Redis数据是存储在内存中的&#xff0c;Redis服务被关闭&#xff0c;数据是会被清除的。但Redis有数据持久化机制&#xff0c;在默认情况下&#xff0c;停止Redis服务会触发数据持久化机制&#xff0c;将数据保存下来&#xff0c;在下次启动时再读取出来。 Re…

解决spring security No AuthenticationProvider found for com.问题

No AuthenticationProvider found for com.xxx.xx 原因 当你验证过&#xff0c;后记得这个这里返回true。不然&#xff0c;就会出现既没有异常&#xff0c;又没验证返回通过的中间尴尬状态&#xff0c;security会当做没有验证通过来处理。 修改

HCIA-存储虚拟化

1、虚拟化概述 KVM是所有云平台的底座&#xff0c;虚拟化是所有云的基础&#xff0c;虚拟化只提供基础架构&#xff0c;云可以提供服务。 CNA是个定制的欧拉系统EulerOS&#xff0c;基于centos内核只保留和虚拟化相关的代码&#xff0c;CNA默认已经部署好kvm虚拟化的软件。CNA…

Visutal Studio2022 如何使用Github copilot

visual studio 2019 升级最新版本的2019也并没有搜索到&#xff0c;直接升级到visual studio 2022&#xff0c;看发布介绍也是2022的copilot Copilot 是一款由 OpenAI 开发的基于 GPT 模型的代码生成工具&#xff0c;可帮助开发者更快地编写代码。如果想在 Visual Studio 中使…

基于大模型的属性操作生成高效训练数据

概述 这篇论文的研究背景是关于利用大型语言模型(LLM)生成高效训练数据的方法。 以往的方法通常是通过LLM生成新的数据&#xff0c;但缺乏对生成数据的控制&#xff0c;这导致了生成数据的信息不足以反映任务要求。本文提出了一种基于LLM的属性操作生成方法&#xff0c;通过精…

如何应对客户报价要求过低的情况?这些方案帮你化解危机!

有个客户在寄样品之前让报价&#xff0c;并且要求承诺价格必须低于15美金&#xff0c;业务员同意了&#xff0c;让客户把样板安排寄到中国&#xff0c;但是收到样品后发现客户的样品在侧面还有一块突出的部分&#xff0c;所以15美金太低了&#xff0c;无论如何也得18美金&#…

计组4——总线Plus IO

(CPU外部的)总线 用于连接computer3大模块(MC/GPUIO) CPU内部的片内总线判优由时序逻辑实现 composition& priority-judging 通信方式 CPU内部的片内总线用于取指、译码、执行、中断的数据通信&#xff1b; IO 总线分为控制线、数据线和地址线&#xff0c;对IO设备的…

Error:Invalid or corrupt jarfile xxx.jar

现象 上传jar包&#xff0c;执行报错&#xff1a;Error&#xff1a;Invalid or corrupt jarfile xxx.jar 解决办法 本地正常执行&#xff0c;上传服务器执行报错。排查发现是因为文件不完整导致&#xff0c;重新上传&#xff0c;比对文件大小&#xff0c;一致后重新执行成功&…

如何在电子设备行业运用IPD?

电子设备是指由集成电路、晶体管、电子管等电子元器件组成&#xff0c;应用电子技术(包括)软件发挥作用的设备&#xff0c;包括电子计算机以及由电子计算机控制的机器人、数控或程控系统等。电子设备基本解释为由微电子器件组成的电器设备。固定资产分类中的电子设备&#xff0…

【重温篇】八大排序——归并排序

思路 归并排序是一种经典的排序算法&#xff0c;采用分治法的思想。它将待排序的数组分成两个较小的子数组&#xff0c;分别对这两个子数组进行排序&#xff0c;然后将排好序的子数组合并成一个有序的数组。 归并排序的主要思路如下&#xff1a; 分解&#xff1a;将待排序的数…

JMETERbeanshell多种姿势获取目标值

beanshell通过vars方式取值 JMETER三种取值方法步骤_securitor的博客-CSDN博客 beanshell通过props方式取值 JMETER取值二_securitor的博客-CSDN博客 beanshell通过source方式取值 JMETER取值三_securitor的博客-CSDN博客 beanshell通过jar包方式取值 JMETER取值四_securitor的…

PHP客服系统-PhpWorkmanChat客服系统修改管理员密码

作为一款流行的开源PHP客服系统&#xff0c;基于thinkphp和workman&#xff0c;跨平台轻量级客服系统源码 管理员表是v2_admin 账户是admin&#xff0c;如果密码忘记了怎么办。可以直接修改数据库表v2_admin &#xff0c;密码规则是md5(密码 加密盐) &#xff0c; 加密盐可以在…

STL源码刨析_stack _queue

目录 一. 介绍 1. stack 介绍 2. queue 介绍 二. 模拟实现 1. stack 模拟实现 2. queue 模拟实现 三. deque 1. deque 接口 2. 底层 一. 介绍 1. stack 介绍 stack&#xff08;栈&#xff09;是一种容器适配器&#xff0c;它提供了一种后进先出&#xff08;LIFO&#xff0…