qiankun 微前端 demo(Vue2)

news2024/11/30 6:38:21

前言

  • 这是我最近刚开始学微前端(qiankun框架)做的一个小demo,做的时候还是遇到很多问题的,在网上也是看了很多别人的Blog,最后也是磨出来了😂😂😂;
  • 这篇文章总统分为分为两部分:
    • 第一部分:是从0到1整个demo的搭建到启动的过程;
    • 第二部分:在整个过程中遇到的各种问题解决和解决办法(后面会陆续补充)。
  • 后面会出一个完整的微前端项目(一个基座 + 两个子应用(B站上面一些培训机构的项目))。
  • 给孩子点点关注吧😭
    image.png

一、demo 搭建 到 启动

1.1 创建 基座 和 微应用

  • Vue创建项目的命令:vue create 项目名称
  • 各项目名称:
    • 基座:app1
    • 子应用:app2 + app3
  • 我是为方便,自己在每个项目下建立了 .env 文件,指定端口:
    • PORT = 指定端口号
    • image.png
    • 各项目端口号:
      • 基座:3001
      • 子应用:
        • app1:3002
        • app2:3003
  • 如果项目中有 Eslint,可以先关闭:
    • 在 vue.config.js 中:image.png

1.2 qiankun 框架下载

  • 只需要 基座 进行 qiankun的下载即可;
  • 命令:
    • npm:npm i qiankun -S
    • yarn: yarn add qiankun

1.3 基座(主应用)配置

  • qiankun官方 主应用配置
  • 以下注册都是在 main.js 中配置的。

1.3.1 从 qiankun 引入两个函数

    // registerMicroApps => 注册微应用
    // start => 启动 qiankun
    import { registerMicroApps, start } from 'qiankun'

1.3.2 注册微应用并启动

  • 我自己是把以下代码前部写在 new Vue()前面的
  • 注册 微应用:
    • registerMicroApps() 参数
    registerMicroApps([
        {
            // 子应用名称
            name: 'App2',
            // 默认会加载这个路径下的html,解析里面的js
            entry: '//localhost:3002',
            // 加载的容器(微应用会显示到这个容器里面,一定要保证主应用中有这个容器)
            container: '#container',
            // 匹配的路由
            activeRule: '/app2'
        },
        {
            name: 'App3',
            entry: '//localhost:3003',
            container: '#container',
            activeRule: '/app3'
        }
    ])
  • 启动 qiankun:
    • start() 参数
    start()
  • 基座(主应用)全部代码展示:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

import { start, registerMicroApps } from 'qiankun'

Vue.config.productionTip = false

// TODO 注册子应用
registerMicroApps([
  {
    // 子应用的名称
    name: 'App2',
    // 默认会加载这个路径下的html,解析里面的js
    entry: '//localhost:3002',
    // 加载的容器
    container: '#container',
    // 匹配的路由
    activeRule: '/app2'
  },
  {
    name: 'App3',
    entry: '//localhost:3003',
    container: '#container',
    activeRule: '/app3'
  },
  {
    name: 'App4',
    entry: '//localhost:8080',
    container: '#container',
    activeRule: '/login?redirect=%2F'
  }
])

// TODO 启动 qiankun
start()

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

1.3.3 基座(主应用)App.vue页面完整代码

<template>
  <div id="app">
    <nav>
      <router-link to="/app2" style="color: blue; fontSize: 25px">App2 - Home</router-link> |
      <router-link to="/app3" style="color: blue; fontSize: 25px">App3 - Home</router-link> |
    </nav>
    <div id="container"></div>
    <router-view/>
  </div>
</template>

<style lang="less">
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}

nav {
  padding: 30px;

  a {
    font-weight: bold;
    color: #2c3e50;

    &.router-link-exact-active {
      color: #42b983;
    }
  }
}
</style>

1.4 微应用配置

1.4.1 在 src下 新增 public-path.js 文件

if (window.__POWERED_BY_QIANKUN__) {
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

1.4.2 微应用 入口文件(main.js) 配置

  • 注意: 很多报错都是出在微应用入口文件的配置
  • router/index.js 中,有 new VueRouter() 这一步,注释掉 new VueRouter()export default router,新增 export default routes(routes就是路由规则数组),就可以直接复制 qiankun官方 关于main.js代码直接使用, qiankun官方文档;
  • image.png
  • 微应用 router/index,js 完整代码:
import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'

Vue.use(VueRouter)

const routes = [
    {
        path: '/',
        name: 'home',
        component: HomeView
    },
    {
        path: '/about',
        name: 'about',
        component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
     }
]

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

// export default router
export default routes
  • 入口文件(main.js)配置:
import './public-path';
import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './App.vue';
import routes from './router';
import store from './store';

Vue.config.productionTip = false;

let router = null;
let instance = null;
function render(props = {}) {
  const { container } = props;
  router = new VueRouter({
    // app3中配置只需将此处的 app2 换成 app3即可,其他的不变
    // 此处的路径,是根据主应用中注册微应用的时候,activeRule字段设置的
    base: window.__POWERED_BY_QIANKUN__ ? '/app2' : '/',
    mode: 'history',
    routes,
  });

  instance = new Vue({
    router,
    store,
    render: (h) => h(App),
  }).$mount(container ? container.querySelector('#app') : '#app');
}

// 独立运行时
if (!window.__POWERED_BY_QIANKUN__) {
  render();
}

export async function bootstrap() {
  console.log('[vue] vue app bootstraped');
}
export async function mount(props) {
  console.log('[vue] props from main framework', props);
  render(props);
}
export async function unmount() {
  instance.$destroy();
  instance.$el.innerHTML = '';
  instance = null;
  router = null;
}

1.4.3 微应用webpack配置

  • 也是直接复制 qiankun官方的代码
  • vue.config.js 中配置
const { defineConfig } = require('@vue/cli-service')
const { name } = require('./package.json');

module.exports = defineConfig({
  transpileDependencies: true,
  lintOnSave: false,
  devServer: {
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  },
  configureWebpack: {
    output: {
      library: `${name}-[name]`,
      libraryTarget: 'umd', // 把微应用打包成 umd 库格式
      /**
      * 此处,qiankun官方是 jsonpFunction: `webpackJsonp_${name}`
      * 具体原因见地位部分 - 
      */ 
      chunkLoadingGlobal: `webpackJsonp_${name}`,
    },
  },
})

1.4.3. 微应用App.vue代码

  • app2:
<template>
  <div id="app">
    <nav>
      <h1 style="color: red; fontSize: 50px">App2 - 我是 3002 端口</h1>
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
    </nav>
    <router-view/>
  </div>
</template>

<style lang="less">
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}

nav {
  padding: 30px;

  a {
    font-weight: bold;
    color: #2c3e50;

    &.router-link-exact-active {
      color: #42b983;
    }
  }
}
</style>

  • app3:
<template>
  <div id="app">
    <nav>
      <h1 style="color: red; fontSize: 50px">App3 - 我是 3003 端口</h1>
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
    </nav>
    <router-view/>
  </div>
</template>

<style lang="less">
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}

nav {
  padding: 30px;

  a {
    font-weight: bold;
    color: #2c3e50;

    &.router-link-exact-active {
      color: #42b983;
    }
  }
}
</style>

二、过程中遇到的问题及解决方法

2.1 需要从微应用中导出生命周期函数

  • 错误:application 'misthin-admin-element' died in status LOADING_SOURCE_CODE: [qiankun]: You need to export lifecycle functions in misthin-admin-element entry
  • 解决办法:
    • 首先去官方看看:qiankun官方常见问题
    • 如果配置什么的都没有问题,还是报这个错误,我自己这边还是 webpack的问题:
      // 在项目中 configureWebpack 属性 是由两个形式的:对象 + 函数
      // 1. 对象形式
      module.exports = defineConfig({
          configureWebpack: {
              output: {
                  library: `${name}-[name]`,
                  libraryTarget: 'umd', // 把微应用打包成 umd 库格式
                  // 需将 jsonpFunction 字段改成 chunkLoadingGlobal
                  // 此处问题见 2.2:webpack配置问题
                  chunkLoadingGlobal: `webpackJsonp_${name}`,
              },
          },
      })
      
      // 2. 函数形式
      /**
      * 如果依然采用上述写法,可能会报错:
      * Avoid modifying webpack output. path directly.  Use the "outputDir" option instead.
      * 避免修改webpack输出。直接路径。请使用“outputDir”选项。
      */
      // 需要改写成下面的形式:
      module.exports = {
          configureWebpack: (config) => {
              config.output.library = `${name}-[name]`
              config.output.libraryTarget = 'umd'
              config.output.jsonpFunction  = `webpackJsonp_${name}`
              config.output.globalObject = 'window'
          }
      };
      

2.2 关于webpack的报错

  • 在 webpack4 中,多个 webpack 运行时可能会在同一个 HTML 页面上发生冲突,因为它们使用同一个全局变量进行代码块加载。为了解决这个问题,需要为 output.jsonpFunction 配置提供一个自定义的名称。
  • Webpack5 确实会从 package.json name 中自动推断出一个唯一的构建名称,并将其作为 output.uniqueName 的默认值。
  • 这个值用于使所有潜在的冲突的全局变量成为唯一。
  • 迁移: 由于 package.json中有唯一的名称,可将output.jsonpFunction 删除。
  • 报错原因: 在2020-10-10发布的webpack5中已将 output.jsonpFunction 更名为 output.chunkLoadingGlobal
  • image.png

2.3 关于项目静态资源加载404问题

  • image.png
  • 问题出现原因:
    • 微应用(子应用)放入到基座(主应用)中后,静态资源会默认走主应用地址去访问,但是主应用中又没有这些静态资源文件,其结果显而易见,肯定就是404了。
  • 解决方法:
    • 原理:publicPath字段设置静态资源路径,默认是走的相对路径,将该字段配置成绝对地址的url即可(子应用部署之后的地址,本地调试的时候,写本地服务地址即可)。
    • 解决方法:
      • 目标文件: vue.config.js
      module.exports = {
          // 设置静态资源访问路径为绝对路径,启动项目的时候,终端显示的地址
          publicPath: 'http://localhost:8080',
          // 修改打包配置
          configureWebpack: {
              // webpack 配置
              output: {
                  library: `${name}-[name]`,
                  libraryTarget: 'umd',
                  jsonpFunction: `webpackJsonp_${name}`
              }
          },
          devServer: {
              // 允许跨域
              headers: {
                  'Access-Control-Allow-Origin': '*',
              },
          },
      }
      
  • publicPath配置选项在各种场景中都非常有用,可以通过它来指定应用程序中所有资源的基础路径。

2.4 其他错误

  • 我主要遇到的就是这个问题,其他的错误可以移步 qiankun官方常见问题;
  • 还有一种可能就是 eSlint导致的。

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

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

相关文章

国产麒麟操作系统 myCat1.6读写分离

我的环境是麒麟操作系统&#xff0c;我只配置读写分离 一、使用说明&#xff0c;java环境&#xff0c;解压就能用 下载地址https://raw.githubusercontent.com/MyCATApache/Mycat-download/master/1.6-RELEASE/Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz mycat 是j…

OJ刷题之旅

题目 现在给你两种颜色的箩筐&#xff0c;需要的时候&#xff0c;就把一个个大小差一圈的筐叠上去&#xff0c;使得从上往下看时&#xff0c;边筐花色交错。这个工作现在要让计算机来完成&#xff0c;得看你的了。 输入 输入是一个个的三元组&#xff0c;分别是&#xff0c;外…

SpringCloud使用SkyWalking实现分布式链路追踪1

文章目录 一、MicrometerTracingBrave(Sleuth)链路追踪1、MicrometerTracingBrave和Zipkin的概论2、Docker搭建Zipkin服务3、MicrometerTracingBrave和Zipkin实现链路追踪 二、SkyWaking服务的安装与使用1、SkyWalking的概论2、Java探针的环境搭建3、Java探针实现日志监控4、Sk…

Netty——介绍和maxContentLength配置

官网 介绍 Netty框架的设计思路是基于NIO的事件驱动编程模型&#xff0c;核心组件包括&#xff1a; Channel&#xff1a;通道&#xff0c;负责网络数据的读写操作&#xff1b; EventLoop&#xff1a;事件循环&#xff0c;处理I/O事件和用户自定义事件&#xff1b; ChannelFut…

【子集树】输出一个序列的子序列

【子集树】输出一个序列的子序列 给一个序列 1 2 3 输出序列的子集 1 2 3 12 13 23 123 如何实现&#xff1f; 由上可以看出 类似于全排列 如何用全排列 实现子集输出&#xff1f; 也就是子集树&#xff1f; #include<iostream>using namespace std;const int N 1e5…

【C++技能树】令常规运算符用在类上 --类的六个成员函数II

Halo&#xff0c;这里是Ppeua。平时主要更新C语言&#xff0c;C&#xff0c;数据结构算法…感兴趣就关注我吧&#xff01;你定不会失望。 本篇导航 0.运算符重载1.赋值运算符 重载2.比较运算符 重载3.比较运算符 ! 重载4.比较运算符 < 重载5.比较运算符 < 重载6. 比较…

图片处理软件:分享6款非常实用的图片处理工具

目录 一、移动端 1、snapseed 2、一键抠图 3、pixlr 二、电脑端 1、图片编辑助手 2.GIMP 3、photopea 今天给大家分享6款非常实用的图片处理工具&#xff0c;其中包含移动端和电脑端&#xff0c;每一款都非常实用&#xff0c;希望对大家能有所帮助&#xff01; 一、移…

《编程思维与实践》1059.计算a的n次方的大整数

《编程思维与实践》1059.计算a的n次方的大整数 题目 思路 高精度的问题统一的解决思路是用一个数组去存大整数的每一位数,运算转化为对数组的操作. 可以从个位开始存(逆序),也可以从最高位开始存(顺序),以处理方便为主要考虑因素. 同时可以将大整数定义为一个结构体,包含位数,…

软件架构:理解分析三层结构观点

三层结构的简单描述及优点   三层体系结构&#xff0c;即用户层、应用层和数据库服务器。用户层主要指用户界面&#xff0c;它要求尽可能的简单&#xff0c;使最终用户不需要进行任何培训就能方便地访问信息&#xff1b;第二层就是应用服务器&#xff0c;也就是常说的中间件&…

webpack: 4 loader汇总(style-loader等)

所有的loader必须匹配规则&#xff0c;否则不生效 配置文件中&#xff0c;module中rules的use执行顺序是从后往前执行 url-loader 用于将文件转换为base64 URI的webpack加载程序。 options limit limit指定文件大小&#xff0c;小于limit的图片不会生成图片以base64格式被引入…

客观地说,应该看一看 Web3.0 了

武术圈有名言&#xff1a;“八极加劈挂&#xff0c;神鬼都害怕”。要是 Web3.0AGI 的话&#xff0c;世界将会变成什么样子&#xff1f; 数科星球原创作者丨苑晶编辑丨大兔 Web3.0 的价值开始受到重视&#xff0c;在最近&#xff0c;来自香港的好消息再次带火了这个领域的热度。…

VMware NSX-T Data Center 3.2.3 - 数据中心网络全栈虚拟化

VMware NSX-T Data Center 3.2.3 - 数据中心网络全栈虚拟化 重要更新&#xff1a;修复 136 个 bug。 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-nsx-t-3/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org VMwa…

ChatGPT 接入飞书教程,创建自己的聊天机器人

ChatGPT 接入飞书教程,创建自己的聊天机器人 一、飞书进入开发者平台。点击创建应用。二、打开Aircode,点击创建应用,上面输入名字,下面选择Node.js v16三、配置环境,点击Environments,创建四个变量,全部要大写本教程收集于: AIGC从入门到精通教程 首先,准备三个账号…

FPGA实现MPEG2视频压缩PCIe传输 提供软硬件工程源码和技术支持

目录 1、前言2、MPEG2视频压缩实现3、我已有的FPGA图像视频编解码方案4、我已有的PCIE方案5、MPEG2视频压缩PCIE传输设计方案FPGA硬件设计软件设计 6、Vivado工程详解7、Linux下的XDMA驱动安装8、上板调试验证9、福利&#xff1a;工程代码的获取 1、前言 MJPEG、MPEG2、MPEG4、…

IOS开发指南之storyboard中控件与变量关联及控件事件与方法关联

1.创建IOS工程 2.选择 interface为storyboard,语言选择Objective-C 打开工程后可看到工程默认添加了两个storyboard文件 Main.storyboard为应用主场景,LaunchScreen为启动屏幕场景 3.双击Main.storyboard打开设计窗口,并拖放控件布局如下 4.为控件添加关联变量与(IBOutlet与I…

身高测量仪红外传感测距模块应用方案 WTU201F2 B004 低功耗

​身高测量仪被广泛用于医疗、教育等领域&#xff0c;而红外测距模块在身高测量仪中的应用则成为了一种新的技术手段。红外测距模块是基于红外线技术的一种测距器件&#xff0c;在身高测量仪中&#xff0c;红外测距模块能够精准地测量出人体的高度。与传统的测量方法相比&#…

品牌如何从零开始运营抖音,带你全面了解

随着短视频逐渐深入我们的生活&#xff0c;巨大的流量吸引了众多人群。很多人因此也想开始做抖音&#xff0c;很多品牌却因为内容制作流程复杂&#xff0c;不知从何入门。今天&#xff0c;和大家分享下品牌如何从零开始运营抖音。 其实在开始一件事情之前&#xff0c;最主要的是…

智能感测离子风棒,托起中国“智”造新高度

智能感测离子风棒采用市面上较为少见的内置感测型离子发生器&#xff0c;能够对外界环境电荷进行快速平衡。该设备智能控制&#xff0c;无需人工点检&#xff0c;达到全自动静电消除并具备异常报警功能。能让ESD管理者或使用者先一步发现问题&#xff0c;快速准确的解决问题 。…

Shell脚本例题

1.计算从1到100所有整数的和 2.提示用户输入一个小于100的整数&#xff0c;并计算从1到该数之间所有整数的和 3.求从1到100所有整数的偶数和、奇数和 4.用户名存放在users.txt文件中&#xff0c;每行一个&#xff0c;判断文件里的用户是否存在&#xff0c;若该用户存在&#xf…

京喜APP - 图片库优化 | 京东云技术团队

作者&#xff1a;京东零售 何骁 介绍 京喜APP早期开发主要是快速原生化迭代替代原有H5&#xff0c;提高用户体验&#xff0c;在这期间也积累了不少性能问题。之后我们开始进行一些性能优化相关的工作&#xff0c;本文主要是介绍京喜图片库相关优化策略以及关于图片相关的一些…