用微前端框架qiankun配置项目的实战

发布于:2022-10-17 ⋅ 阅读:(934) ⋅ 点赞:(0)

参考文档:

 

qiankun官方文档      csdn文档1      github地址

umi-qiankun 的教程请移步 umi 官网 和 umi-qiankun 的官方 demo

一、过程

1.使用vue-cli创建主应用

vue create qiankun-main

选择2.x版本,选择eslint等等配置,完成后初始化并启动项目。vue-cli建的项目vue版本是2.6,所以不要用ts。

2.主应用需要安装qiankun插件   

npm i qiankun -S

3.配置些简单的eslint 和 prettierrc规则

注意  "vue/multi-word-component-names": "off",  要添加,否则创建view下其他vue文件如index.vue时会报错。

// in .eslintrc.js

module.exports = {
  root: true,
  env: {
    node: true,
  },
  extends: [
    "plugin:vue/essential",
    // "plugin:prettier/recommended",  // 还没配置prettier就先注释掉
  ],
  parserOptions: {
    parser: "@babel/eslint-parser",
    ecmaVersion: 2020,
  },
  rules: {
    "no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
    "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
  },
  overrides: [
    {
      files: ["*.vue"], // 匹配views和二级目录中的index.vue
      rules: {
        "vue/multi-word-component-names": "off",
      }, //给上面匹配的文件指定规则
    },
  ],
};
// in .prettierrc.js

module.exports = {
  // 一行最多 120 字符..
  printWidth: 120,
  // 使用 2 个空格缩进
  tabWidth: 2,
  // 不使用缩进符,而使用空格
  useTabs: false,
  // 行尾需要有分号
  semi: true,
  // 使用单引号
  singleQuote: true,
  // 对象的 key 仅在必要时用引号
  quoteProps: 'as-needed',
  // jsx 不使用单引号,而使用双引号
  jsxSingleQuote: false,
  // 末尾需要有逗号
  trailingComma: 'all',
  // 大括号内的首尾需要空格
  bracketSpacing: true,
  // jsx 标签的反尖括号需要换行
  jsxBracketSameLine: false,
  // 箭头函数,只有一个参数的时候,也需要括号
  arrowParens: 'always',
  // 每个文件格式化的范围是文件的全部内容
  rangeStart: 0,
  rangeEnd: Infinity,
  // 不需要写文件开头的 @prettier
  requirePragma: false,
  // 不需要自动在文件开头插入 @prettier
  insertPragma: false,
  // 使用默认的折行标准
  proseWrap: 'preserve',
  // 根据显示样式决定 html 要不要折行
  htmlWhitespaceSensitivity: 'css',
  // vue 文件中的 script 和 style 内不用缩进
  vueIndentScriptAndStyle: false,
  // 换行符使用 lf
  endOfLine: 'lf',
};

4.配置新路由

删除无用代码比如HomeView.vue等文件,重新配置路由。

配置些简单的路由:

// in src/router/index.ts

import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../views/home/index.vue";

Vue.use(VueRouter);

const routes = [
  {
    path: "/",
    name: "home",
    component: Home,
  },
  {
    path: "/about",
    name: "about",
    component: () => import("../views/about/index.vue"),
  },
];

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

export default router;

5.编写存放微应用的区域

参考上方文档1.

我选择在 src/views/home/index.vue 中存放:

<template>
  <div class="home">
    <h1>主应用首页</h1>
    <div class="app-content">
      <!-- 微应用所在 -->
      <div id="root-view"></div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { reactive, ref, onMounted } from 'vue';

const showPage = ref<Boolean>(false);
onMounted(() => {
  console.log(31, '首页', showPage.value);
});
</script>

6. 注册微应用并启动

可以上方参考官方文档项目实践部分,或者文档1实战部分

src下新建modules文件夹,里面新建micro-app.ts。 这是注册微应用的代码。

// in src/modules/micro-app.ts

// 在主应用中注册微应用    各子应用信息如下
const microApps = [
  {
    name: "module-app1", // name都不能重复
    entry: "http://localhost:8090", // 定义子应用入口,基于qiankun的应用一般直接写子应用的入口html地址即可。
    activeRule: "/app1", // url变化后, 所有 activeRule 规则匹配上的微应用就会被插入到指定的 container 中
    container: "#root-view", // 定义子应用的加载位置,如 id为root-view的一个盒子
    sandbox: {
      strictStyleIsolation: true, // 开启样式隔离
    },
  },
  {
    name: "module-shop",
    entry: "https://app2.example.com",
    activeRule: "/app2",
    container: "#root-view",
    sandbox: {
      strictStyleIsolation: true, // 开启样式隔离
    },
  },
];
export default microApps;

启动:

在  src/views/home/index.vue   页添加相应代码:

<template>
  <div class="home">
    <h1>主应用首页</h1>
    <div class="app-content">
      <!-- 微应用所在 -->
      <div id="root-view"></div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import microApps from '../../modules/micro-app';
import { reactive, ref, onMounted } from 'vue';
// // 引入qiankun注册子应用和启动的接口函数
import { registerMicroApps, start } from 'qiankun';

// 引入微应用入口配置
registerMicroApps(microApps, {
  // 注册一些全局生命周期钩子,如进行日志打印,如果不需要可以不传
  //   beforeMount() {
  //     console.log(22, "qiankun");
  //   },
});
// 启动qiankun,并开启预加载
start({ prefetch: true });

const showPage = ref<Boolean>(false);
onMounted(() => {
  console.log(31, '首页', showPage.value);
});
</script>

7.在微应用进行相应配置:

参考官方文档:

①在 src 目录新增  public-path.js 文件

// 在qiankun环境下,修正加载路径
if (window.__POWERED_BY_QIANKUN__) {
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

②入口文件 main.js 修改:

import Vue from 'vue';
import App from './App.vue';
import VueRouter from 'vue-router';
import routes from './router';
import store from './store';

Vue.config.productionTip = false;

let router = null;
let instance = null;
function render(props = {}) {
  const { container } = props;
  //   Vue.use(VueRouter);
  router = new VueRouter({
    base: window.__POWERED_BY_QIANKUN__ ? '/app2/' : '/',
    mode: 'history',
    routes,
  });

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

// 独立运行时(在非qiankun环境下,直接执行渲染)
if (!window.__POWERED_BY_QIANKUN__) {
  render();
}

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

/**
 * 挂载函数
 * 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
 */
export async function mount(props: any) {
  console.log('[vue] props from main framework', props);
  render(props);
}

/**
 * 卸载函数
 * 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
 */
export async function unmount() {
  instance.$destroy();
  instance.$el.innerHTML = '';
  instance = null;
  router = null;
}
/**
 * 可选生命周期钩子,仅使用 loadMicroApp 方式加载微应用时生效
 */
export async function update(props: any) {
  console.log('update props', props);
}

注意,要修改 src/router/index.ts 文件,此时该文件导出的应该是路由信息数组:

import Vue from "vue";
// import VueRouter from "vue-router";
import Home from "../views/home/index.vue";

// Vue.use(VueRouter);

const routes = [
  {
    path: "/",
    name: "home",
    component: Home,
  },
  {
    path: "/about",
    name: "about",
    component: () => import("../views/about/index.vue"),
  },
];

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

export default routes;

③ 打包配置修改(vue.config.js):

const { defineConfig } = require("@vue/cli-service");
const { name } = require('./package');
module.exports = defineConfig({
  transpileDependencies: true,
  devServer: {
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  },
  configureWebpack: {
    output: {
      library: `${name}_[name]`,
      libraryTarget: 'umd', // 把微应用打包成 umd 库格式
      chunkLoadingGlobal: `webpackJsonp_${name}`,
    },
  },
});

注意:官方文档里是jsonpFunction: `webpackJsonp_${name}`,。这样会报错:

 搜索 报错 configuration has an unknown property ‘jsonpFunction‘ ,见文档

webpack  在2020-10-10发布的webpack 5中已将 output.jsonpFunction 更名为 output.chunkLoadingGlobal 。所以要把 jsonpFunction 改为 chunkLoadingGlobal 。

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到