qiankun前端微服务框架

一.须知

本文基于同一服务器不同端口进行配置

  • 主应用: 支持任意技术栈,无限制
  • 微应用: 暂不支持vite2.x 版本,因为vite打包代码时,内部的esbuild会tree shake掉与qiankun相关的生命周期钩子
  • 官方文档qiankun

如需部署在 同一服务器同一端口
请查看该篇:qiankun前端微服务框架-同一服务器同一端口

二.主应用配置

  • 主应用配置相对简单,只需main.js和app.vue中的部分方法即可

2.1 main.js

import { createApp } from "vue";
import App from "./App.vue";
import Router from "./router";
import store from "./store";
// 导出qiankun函数
import { registerMicroApps, setDefaultMountApp, start } from "qiankun";
//匹配路由
function genActiveRule(routerPrefix) {
  return (location) => location.pathname.startsWith(routerPrefix);
}

let app = createApp(App);
app.use(Router);
app.use(store);
app.mount("#app");

let msg = {
  data: "传的值",
};

let apps = [
  {
    name: "a-child",
    entry: "//localhost:6601",
    container: "#subView",
    activeRule: genActiveRule("/a-child"),
    props: msg,
  },
  {
    name: "b-child",
    entry: "//localhost:6602",
    container: "#subView",
    activeRule: genActiveRule("/b-child"),
    props: msg,
  },
];

//注册的子应用 参数为数组
registerMicroApps(apps, {
  beforeLoad: [
    (app) => {
      console.log("beforeLoad");
    },
  ],
  beforeMount: [
    (app) => {
      console.log("beforeMount");
    },
  ],
  afterUnmount: [
    (app) => {
      console.log("afterUnmount");
    },
  ],
});
//设置默认初始入口
// setDefaultMountApp("/a-child/xixi");
//启动时配置
start({ experimentalStyleIsolation: true, prefetch: "all" });

2.2 app.vue

<template>
  <div id="app">
    <div @click="onChangePage('/a-child/xixi')">微应用一号</div>
    <div @click="onChangePage('/b-child/wuwu')">微应用二号</div>
    <div id="subView"></div>
  </div>
</template>
<script>
import { mapState } from "vuex";
export default {
  data() {
    return {};
  },
  methods: {
    //改变路由
    onChangePage(url) {
      console.log(url);
      this.routerGo(url, "测试页面");
    },
    routerGo(href = "/", title = null, stateObj = {}) {
      window.history.pushState(stateObj, title, href);
    },
  },
};
</script>

三.微应用配置

3.1 注册

须知:

  • 所有的资源(图片/音视频等)都应该放到 src 目录,不要放在 public 或 者static
    资源放 src 目录,会经过 webpack 处理,能统一注入 publicPath。否则在主项目中会404

3.1.1 vue.config.js配置

const path = require("path");
const packageName = require("./package.json").name;

function resolve(dir) {
  return path.join(__dirname, dir);
}

const dev = process.env.NODE_ENV === "development";

const port = 6601; // dev port

module.exports = {
  publicPath: dev ? `//localhost:${port}` : "/",

  outputDir: "dist",
  assetsDir: "static",
  filenameHashing: true,

  devServer: {
    hot: true,
    historyApiFallback: true,
    port,
    overlay: {
      warnings: false,
      errors: true,
    },
    headers: {
      "Access-Control-Allow-Origin": "*",
    },
  },
  // 自定义webpack配置
  configureWebpack: {
    resolve: {
      alias: {
        "@": resolve("src"),
      },
    },
    output: {
      library: `${packageName}-[name]`,
      libraryTarget: "umd",
      jsonpFunction: `webpackJsonp_${packageName}`,
      globalObject: "this",
    },
  },
};

3.1.2 新增文件 publicPath.js

  • src目录下新建 publicPath.js , 用户在vue.config.js中引用使用
if (window.__POWERED_BY_QIANKUN__) { 
  //处理资源
   __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__; 
  }

3.1.3 不同微应用vue版本的main.js

  • router创建方式不同
  • 卸载微应用实例的方式不同
    vue2 为instance.$destory()
    vue3 为instance.unmount()
vue2
import "./publicPath.js";
import Vue from "vue";
import App from "./App.vue";
import routes from "./router";
import VueRouter from "vue-router";
import store from "./store";

Vue.config.productionTip = false;

let router = null;
let instance = null;

//下面的 /star  与主应用  registerMicroApps 中的  activeRule 字段对应
function render({ container } = {}) {
  router = new VueRouter({
    base: window.__POWERED_BY_QIANKUN__ ? "/a-child" : process.env.BASE_URL,
    mode: "history",
    routes,
  });

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

if (!window.__POWERED_BY_QIANKUN__) {
  render();
}
/**
 * bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
 * 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
 */
export async function bootstrap() {
  console.log("[a-child vue] vue app bootstraped");
}

//应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
export async function mount(props) {
  //props 包含主应用传递的参数  也包括为子应用 创建的节点信息
  render(props);
}

//应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
export async function unmount() {
  instance.$destroy();
  instance.$el.innerHTML = "";
  instance = null;
  router = null;
}
vue3
import "./publicPath.js";
import { createApp } from "vue";
import App from "./App.vue";
import routes from "./router";
import { createRouter, createWebHistory } from "vue-router";
import store from "./store";

let instance = null;
let router = null;

function render({ container } = {}) {
  router = createRouter({
    history: createWebHistory(window.__POWERED_BY_QIANKUN__ ? "/b-child" : "/"),
    routes,
  });

  instance = createApp(App);
  instance.use(router);
  instance.use(store);
  instance.mount(container ? container.querySelector("#bChild") : "#bChild");
}

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

/**
 * bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
 * 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
 */
export async function bootstrap() {}

//应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
export async function mount(props) {
  render(props);
}

//应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
export async function unmount() {
  instance.unmount();   //和vue2的区别
  instance._container = "";
  instance = null;
  router = null;
}

3.1.4 命名空间要保证唯一性

  • index.html中的 id
  • package.json中的name

四.参考文章[强烈推荐]

1.https://cloud.tencent.com/developer/article/1814160
2.qiankun 微前端方案实践及总结
3.qiankun 微前端实践总结(二)

如何创建Vue3项目

vue3和vue2创建项目区别
- 安装到最新版后,初始化项目时可选择创建vue2还是vue3版本,更具人性化与兼容性

vue3

npm install -g @vue/cli --force:安装vue cli
vue create app:初始化项目


vue2

npm install --global vue-cli:安装vue cli
vue create app
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

情系半生e

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值