【前端微服务】qiankun

前端微服务

  • 目录
      • main为主项目 app-vue-history vue-test 为子项目
  • qiankun是什么?
    • 构建主项目
      • 修改主项目app.vue
    • 子项目构建
      • 修改vue.config.js
      • 创建文件public-path
      • 修改main.js
  • 项目内通信
    • qiankun全局通讯
    • 全局组件使用
    • 父子项目store公用
      • 主项目传递
    • 全局参数
    • 关于vite 打包

技术栈:vue3、typescript、qiankun(阿里的微前端框架)、vue-cli4、vue2、webpack


目录

【前端微服务】qiankun_第1张图片

main为主项目 app-vue-history vue-test 为子项目


qiankun是什么?

qiankun 是一个基于 single-spa 的微前端实现库,旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统

构建主项目

安装 qiankun

yarn add qiankun
或者
npm i qiankun -S

修改主项目app.vue

import 'whatwg-fetch';
import 'custom-event-polyfill';
import 'core-js/stable/promise';
import 'core-js/stable/symbol';
import 'core-js/stable/string/starts-with';
import 'core-js/web/url';
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import { registerMicroApps, start } from 'qiankun';
import testComponent from "./components/test-component" //引入组件
Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount("#app");
window.commonComponent = { testComponent }; // 全局组件
localStorage.setItem("test",111)  // 缓存数据
registerMicroApps([
  {
    name: 'app-vue-history',
    entry: 'http://127.0.0.1:2222',
    container: '#appContainer',
    activeRule: '/app-vue-history',
    props: { data : store }
  },
  {
    name: 'vue-test',
    entry: 'http://127.0.0.1:3333',
    container: '#appContainer',
    activeRule: '/vue-test',
      props: { data : store }
  },
]);

start();

子项目构建

利用vue-cli 创建项目

vue create vue-test
cd vue-test
yarn add vue-router vuex
yarn 

修改vue.config.js

const { name } = require('./package');
module.exports = {
  devServer: {
    port: 2222,
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  },
  chainWebpack: (config) => {
    config.module
      .rule('fonts')
      .test(/.(ttf|otf|eot|woff|woff2)$/)
      .use('url-loader')
      .loader('url-loader')
      .tap(options => ({ name: '/fonts/[name].[hash:8].[ext]' }))
      .end()
  },
  // 自定义webpack配置
  configureWebpack: {
    output: {
      library: `${name}-[name]`,
      libraryTarget: 'umd',// 把子应用打包成 umd 库格式
      jsonpFunction: `webpackJsonp_${name}`,
    },
  },
};

创建文件public-path

if (window.__POWERED_BY_QIANKUN__) {
  // eslint-disable-next-line no-undef
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

修改main.js

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

Vue.config.productionTip = false;

let router = null;
let instance = null;

function render({container, store} = {}) {
    router = new VueRouter({
        base: window.__POWERED_BY_QIANKUN__ ? '/vue-test' : '/', mode: 'history', routes,
    });
    Vue.prototype.testStore = testStore

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

if (!window.__POWERED_BY_QIANKUN__) {
    render();
}
//测试全局变量污染
window.a = 1;

export async function bootstrap() {
    console.log('vue app bootstraped');
}

export async function mount(props) {
    console.log('props from main framework', props);
    render(props);
    // 测试一下 body 的事件,不会被沙箱移除
    // document.body.addEventListener('click', e => console.log('document.body.addEventListener'))
    // document.body.onclick = e => console.log('document.body.addEventListener')
}

export async function unmount() {
    instance.$destroy();
    instance.$el.innerHTML = "";
    instance = null;
    router = null;
}


项目内通信

qiankun全局通讯

主应用

import { initGlobalState, MicroAppStateActions } from 'qiankun';

// 初始化 state
const actions: MicroAppStateActions = initGlobalState(state);

actions.onGlobalStateChange((state, prev) => {
  // state: 变更后的状态; prev 变更前的状态
  console.log(state, prev);
});
actions.setGlobalState(state);
actions.offGlobalStateChange();

子应用

// 从生命周期 mount 中获取通信方法,使用方式和 master 一致
export function mount(props) {
  props.onGlobalStateChange((state, prev) => {
    // state: 变更后的状态; prev 变更前的状态
    console.log(state, prev);
  });

  props.setGlobalState(state);
}

全局组件使用

主项目main.js

import testComponent from "./components/test-component"
window.commonComponent = { testComponent };

子项目使用

<template>
  <div id="app">
      <testComponent msg="测试子项目公共组件2"></testComponent>
  </div>
</template>
<script>

export default {
  name: 'App',
  components: {
      testComponent:testComponent:window.__POWERED_BY_QIANKUN__ ? window.commonComponent.testComponent : import('@/components/test-component')
  },

}
</script>

父子项目store公用

主项目传递

主项目

import store from './store'
registerMicroApps([
  {
    name: 'vue-test',
    entry: 'http://127.0.0.1:3333',
    container: '#appContainer',
    activeRule: '/vue-test',
      props: { data : store }
  },
  ]

子项目

import testStore from './store';
Vue.prototype.testStore = testStore
 // 项目使用
this.microStore.state.microCount

全局参数

window
localstorage
cookie

关于vite 打包

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { name } from './package.json'
import html from '@rollup/plugin-html';

// https://vitejs.dev/config/
export default defineConfig({
  base: 'http://localhost:3333/',
  plugins: [vue(), html({
    // copy 自 https://github.com/rollup/plugins/blob/db4a3f2e8ebd3328b5d43bcb272589866dfd5729/packages/html/src/index.ts#L34
    template: ({ attributes, files, meta, publicPath, title }) => {
      const makeHtmlAttributes = (attributes) => {
        if (!attributes) {
          return '';
        }
        const keys = Object.keys(attributes);
        return keys.reduce((result, key) => (result += ` ${key}="${attributes[key]}"`), '');
      };
      const scripts = (files.js || [])
        .map(({ fileName }) => {
          const attrs = makeHtmlAttributes(attributes.script);
          return ``;
        })
        .join('\n');
    
      const links = (files.css || [])
        .map(({ fileName }) => {
          const attrs = makeHtmlAttributes(attributes.link);
          return `${publicPath}${fileName}" rel="stylesheet"${attrs}>`;
        })
        .join('\n');
    
      const metas = meta
        .map((input) => {
          const attrs = makeHtmlAttributes(input);
          return `${attrs}>`;
        })
        .join('\n');
    
      return `
        ${makeHtmlAttributes(attributes.html)}>
          
            ${metas}
            </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>title<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">
            ${links}
            
          
          
            
${scripts} `
; } })], build: { // assetsInlineLimit: 0, // 为了让图片单独打包 target: "esnext", lib: { name, entry: 'src/main.ts', formats: ['umd'], }, }, })

你可能感兴趣的:(it初学者,im,学习,前端)