qiankun 微前端 demo(Vue2)

前言

  • 这是我最近刚开始学微前端(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导致的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

windows 编译 opencv

编译需要的基础工具 #cmake是配置构建工具&#xff0c;mingw是编译工具 cmake CMake是一款跨平台的编译管理工具&#xff0c;可以自动生成各种不同编译环境&#xff08;如Makefile、Visual Studio Solution等&#xff09;&#xff0c;从而实现在不同平台上进行代码编译的目的…

Qwik 1.0 发布,全栈式 Web 框架

Qwik 是一个全栈式 Web 框架&#xff0c;Qwik 基于 React、Angular 和 Vue 等其他 Web 框架的概念&#xff0c;但以 JavaScript 流等更新的方法脱颖而出&#xff0c;允许以高性能向用户交付复杂的 Web 应用程序。 随着 Web 应用程序变得越来越大&#xff0c;它们的启动性能会下…

强烈推荐:一款中文AI问答、创作、绘画工具

前言 相信很多人已经听过ChatGPT这款人工智能机器人了&#xff0c;它能够根据用户输入的内容&#xff0c;自动生成智能回复。它使用自然语言处理技术&#xff0c;通过学习大量的文本资料&#xff0c;能够模拟人类的对话行为。它是由OpenAI开发的&#xff0c;一家非常伟大的人工…

Http知识

一、http协议 目前存在HTTP1.1&#xff08;当前广泛运用的版本&#xff09;、HTTP2.0和HTTP3.0协议&#xff0c;有以下的优点和缺点 1. HTTP1.1 优点&#xff1a;默认支持长连接&#xff0c;即在一个TCP连接上可以传送多个HTTP请求和响应&#xff0c;减少了建立和关闭连接的…

Flutter框架:从入门到实战,构建跨平台移动应用的全流程解析

第一章&#xff1a;Flutter框架介绍 Flutter框架是由Google推出的一款跨平台移动应用开发框架。相比其他跨平台框架&#xff0c;Flutter具有更高的性能和更好的用户体验。本章将介绍Flutter框架的概念、特点以及与其他跨平台框架的比较&#xff0c;以及Flutter开发环境的搭建和…

应急物流 | 灾后早期阶段多目标选址路径问题的混合元启发式算法

解读作者&#xff1a;李奡&#xff0c;闫同仁 A hybrid meta-heuristic algorithm for the multi-objective location-routing problem in the early post-disaster stage Tongren Yan, Fuqiang Lu, Suxin Wang, Leizhen Wang, Hualing Bi Journal of industrial and managem…

设计原则之【接口隔离原则】,我只做我能做的事

文章目录 一、什么是接口隔离原则二、实例三、总结接口隔离原则与单一职责原则的区别 一、什么是接口隔离原则 接口隔离原则&#xff08;Interface Segregation Principle, ISP&#xff09;是指用多个专门的接口&#xff0c;而不使用单一的总接口&#xff0c;客户端不应该依赖…

【中级软件设计师】—(下午题)试题三精讲总结(四十二)

【中级软件设计师】—&#xff08;下午题&#xff09;试题三精讲总结&#xff08;四十二&#xff09; 一、关系 二、UML中的图 A包含B&#xff0c;那么A执行操作前必须要先执行B 试题一&#xff08;2021年下半年&#xff09; 试题2&#xff08;2021年上半年&#xff09; 官方…

Docker中部署监控

Docker概念 一、部署Prometheus+grafana环境 1.1 、部署Prometheus+grafana环境 docker pull registry.cn-hangzhou.aliyuncs.com/lhrbest/lhrprometheus:1.0 docker tag registry.cn-hangzhou.aliyuncs.com/lhrbest/lhrprometheus:1.0 lhrbest/lhrprometheus:1.01.2 、创建镜…

linux 定时器

Linux 系统实现底半部的机制主要有tasklet&#xff0c;工作队列和软中断。 tasklet 和工作队列都是调度中断底半部的良好机制&#xff0c;tasklet 基于软中断实现。 内核定时器也依靠软中断实现;内核中的延时是忙等待或者睡眠等待&#xff0c;为了充分利用CPU资源&#xff0c…

docker 搭建 Elasticsearch和Kibana 8.x版本

参考: docker入门&#xff1a;单机elasticsearch安装记录&#xff0c;保证无坑_8月日更_小鲍侃java_InfoQ写作社区 新建文件夹 同上文所述相同&#xff0c;需要在宿主机上挂载配置文件与数据文件。 mkdir -p /Users/louye/data/learn-data/elastic/config mkdir -p /Users/lo…

从地方旅游的宣传谈起:如何吸引主流媒体报道,强势刷屏?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 五一小长假已经过去好几天了&#xff0c;大家渐渐的从假期舒适的闲暇转到正常的工作生活中了&#xff0c;但利用五一热点宣传的余温还在继续&#xff0c;今天胡老师就i注意到一篇题为&am…

华为nqa实验拓扑案例

nqa是一种实时的网络性能探测和统计技术&#xff0c;可以对响应时间、网络抖动、丢包率等网络信息进行统计。如图1所示&#xff0c;接口备份与NQA联动功能配置相对简单&#xff0c;只需在本端RouterA上配置NQA测试例&#xff0c;并在RouterA的备份接口上配置接口备份与NQA联动&…

重写Properties类,实现对properties文件的有序读写,数据追加,解决中文乱码

前言 *.properties文件&#xff0c;是 Java 支持的一种配置文件类型&#xff0c;并且 Java 提供了 properties 类来读取 properties 文件中的信息。文件中以键值对 "键值"的形式&#xff0c;存储工程中会多次重复使用的配置信息&#xff0c;通过“Properties”类来读…

4.Redis10大数据类型

Redis10大数据类型 Which 101.String&#xff08;字符串&#xff09;2.List&#xff08;列表&#xff09;3.hash &#xff08;哈希&#xff09;4.Set&#xff08;集合&#xff09;5.zset(sorted set&#xff1a;有序集合)6.Redis GEO &#xff08;地理空间&#xff09;7.HyperL…

Linux最常用的15个基本命令

目录 Linux基本命令 命令1&#xff1a;ls &#xff08;查看指定目录中有哪些内容&#xff09; ls / 相当于查看根目录中的内容&#xff0c;相当于查看我的电脑 ls -l&#xff08;小写l&#xff0c;或者使用ll&#xff09;详细查看目录下所有内容 ls /usr/lib&#xff08…

“AI代劳”,跨域赋能“智慧企业”

随着全球数字信息化的到来&#xff0c;各大新兴行业企业也逐渐意识到“智慧化”转型的重要性&#xff0c;但目前仍有不少企业在面临着人力成本高、运营管理效率低、营销获客效果差、数据分析能力薄弱等瓶颈&#xff0c;那么&#xff0c;处于这些瓶颈期的企业该如何实现“智慧化…

【Java零基础入门篇】第 ④ 期 - 继承(二)

博主&#xff1a;命运之光 专栏&#xff1a;JAVA入门 学习目标 1.掌握继承性的主要作用、实现、使用限制&#xff1b; 2.掌握this和super的含义及其用法&#xff1b; 3.掌握方法覆写的操作&#xff1b; 4.掌握final关键字的使用&#xff1b; 5.掌握类变量、实例变量和局部变量的…

数据库创建与管理

目录 一、创建数据库 1&#xff0e;准备创建数据库 2&#xff0e;创建数据库实例分析 方法一&#xff1a;使用对象资源或企业管理器创建数据库 方法二&#xff1a;使用Transact-SQL命令创建数据库 二、管理数据库 1&#xff0e;修改数据库 使用SQL命令修改数据库 2&…

如何将ChatGPT训练成某个领域的专家!附完整示例!

背景 最近听了 八叉的一个ChatGPT讲座&#xff0c;讲的是如何将ChatGPT训练成领域专家&#xff0c;这样我们就可以用它来解决该领域的各种问题。 整个讲座中最让我印象深刻的就是训练方法&#xff0c;它是通过让ChatGPT向我们提问&#xff0c;然后由我们给出答案的方式进行训…