美文网首页
微前端 qiankun + Vite + Vue3 + Vue2

微前端 qiankun + Vite + Vue3 + Vue2

作者: Avery_G | 来源:发表于2023-03-21 15:18 被阅读0次

    qiankun 是什么

    qiankun 是基于 single-spa 的微前端实现库,可以帮助大家更快速的构建一个前端微架构体系。

    微前端是什么

    官方给出的概念是:微前端是一种多个团队通过独立发布功能的方式来共同构建现代化 web 应用的技术手段及方法策略。简单理解就是一个大型项目中,有一个主应用,N 个子应用,各个应用之间可以独立开发,独立运行,独立部署。

    为什么要用微前端

    我们应该都有这样的经历,一个项目一直在更新迭代,参与的人也越来越多,代码也越来越多,导致项目越来越不好管理,打包速度越来越慢,打包体积越来越大,部署不方便。尤其是在有一个很小的需求要更新时,我们需要重新打包部署整个项目,就很头大。所以我们就需要微前端,把一个单一的应用,转换为多个可以独立开发、测试、部署的小应用。但用户是无感知的,依旧认为是一个产品。

    开始搭建微前端的主应用(基座)

    安装 qiankun

    yarn add qiankun # 或者 npm i qiankun -S
    

    在主应用中注册微应用

    我们在 src 文件夹下新建一个 qiankun/index.ts ,用来放我们的 qiankun 的配置信息

    // src/qiankun/index.ts
    import {registerMicroApps, start} from 'qiankun';
    
    registerMicroApps([
        {
            name: 'qiankun-demo-b', // 子应用的注册名称,即子应用 package.json 中的 name 
            entry: '//localhost:5174', // 子应用的启动地址
            container: '#app-b',  // 承载子应用的容器,在主应用中,有一个 ID 为 app-b 的 div,用来承载子应用
            activeRule: '/about',  // 点击哪个路由会进入子应用
        },
        /*
        * 比如,我在 app.vue 文件中注册了两个路由
        * <template>
              <nav>
                <RouterLink to="/">Home</RouterLink>
                <RouterLink to="/about">About</RouterLink>
              </nav>
            
              <RouterView />
            </template>
        * 那么这个 activeRule: '/about' 对应的就是 <RouterLink to="/about">About</RouterLink> 这个路由
        * 之后,我在 about.vue 这个文件中,添加一个承载子应用的 div,那么这个 container: '#app-b' 对应的就是 <div id="app-b"></div> 这个 div
        * <template>
              <div class="about">
                <h1>This is an about page 111</h1>
                <div id="app-b"></div>
              </div>
            </template>
        * 有多个子应用,可以按这种方式来配置多个
        * */
        {
            name: 'qiankun-demo-d',
            entry: '//localhost:8080',
            container: '#app-d',
            activeRule: '/car',
        }
    ]);
    
    start();
    
    

    在 main.ts 中引入

    // 引入qiankun
    import './qiankun/index'
    

    微应用

    Vue3 + Vite

    我们先来看 Vue 微应用,Vue 微应用有一个点需要注意的就是 Vite , qiankun 与 Vite 不能一起使用,所以需要额外安装一个插件,以下是使用 Vite 时 qiankun 的配置

    npm install vite-plugin-qiankun
    

    微应用需要在自己的入口 js 导出 bootstrapmountunmount 三个生命周期钩子,以供主应用在适当的时机调用。
    我们来修改子应用里的 main.ts 文件

    // main.ts
    import {createApp} from 'vue'
    import App from './App.vue'
    import router from './router'
    
    import './assets/main.css'
    
    import {renderWithQiankun, qiankunWindow} from 'vite-plugin-qiankun/dist/helper'
    
    let instance: any = null
    function render(props: any = {}) {
        const { container } = props
        instance = createApp(App)
        instance.use(router)
        instance?.mount(container ? container.querySelector('#app') : '#app')
        console.log('开始加载相关内容')
    }
    /*
    * bootstrap :
    * 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
    * 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
    * mount :
    *  应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
    * unmount :
    *  应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
    * update :
    * 可选生命周期钩子,仅使用 loadMicroApp 方式加载微应用时生效
    * */
    renderWithQiankun({
        mount(props: any) {
            // 应用每次进入都会调用 mount 方法,所以我们在这里初始化一些内容
            render(props)
        },
        bootstrap() {
            console.log('微应用初始化的时候调用一次')
        },
        update() {
            console.log('update')
        },
        unmount(props: any) {
            console.log('unmount:应用每次 切出/卸载 会调用的方法', props)
            instance.unmount()
            instance._container.innerHTML = ''
            instance = null
        }
    })
    /*
    * 通过 qiankunWindow.__POWERED_BY_QIANKUN__ 判断是不是 qiankun 渲染的,如果不是 qiankun 渲染的,需要调用以下 render 方法来初始化一些内容
    * */
    if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
        console.log('并不是qiankun渲染')
        render()
    }
    
    

    打包配置修改,需要配置微应用的名字与端口号,使其与主应用配置的微应用保持一致

     // vite.config.js
    import { fileURLToPath, URL } from 'node:url'
    
    import { defineConfig } from 'vite'
    import vue from '@vitejs/plugin-vue'
    import qiankun from 'vite-plugin-qiankun'
    
    export default defineConfig({
        plugins: [
            vue(),
            qiankun('vue-app', { // 微应用名字,与主应用注册的微应用名字保持一致
                useDevMode: true
            })
        ],
        server: {
            port: 5174  // 微应用端口号,与主应用注册的微应用保持一致
        },
        resolve: {
            alias: {
                '@': fileURLToPath(new URL('./src', import.meta.url))
            }
        }
    })
    

    Vue3 不使用 Vite

    这里我们就不需要安装任何插件了,只需在微应用的入口文件导出 bootstrapmountunmount 三个生命周期钩子,以供主应用在适当的时机调用就可以了。
    同样还是修改 main.ts 文件,这里的思路和 Vue3 + Vite 的是一样的,只是写法略微不同而已

    // main.ts
    import { createApp } from 'vue'
    import App from './App.vue'
    import router from './router'
    import store from './store'
    
    
    let app = null;
    
    function render(props = {}) {
        const { container } = props;
        app = createApp(App);
        app
            .use(store)
            .use(router)
            .mount(container ? container.querySelector("#app") : "#app");
    }
    
    // 独立运行时
    // 这里和 Vue3 + Vite 不太一样,是通过 window.__POWERED_BY_QIANKUN__ 来判断是否是 qiankun 渲染的
    if (!window.__POWERED_BY_QIANKUN__) {
        console.log('独立运行')
        render();
    }
    
    export async function bootstrap() {
        console.log('微应用初始化的时候调用一次');
    }
    export async function mount(props) {
        console.log("mount", props);
        render(props);
    }
    export async function unmount() {
        app.unmount();
    }
    

    打包配置修改,需要配置微应用的名字与端口号,使其与主应用配置的保持一致

     // vue.config.ts
    const { defineConfig } = require('@vue/cli-service')
    const { name } = require('./package');
    module.exports = defineConfig({
        transpileDependencies: true,
        publicPath: "http://localhost:8080/",
        devServer: {
            port: 8080, // 微应用端口号,与主应用注册的微应用保持一致
            headers: {
                'Access-Control-Allow-Origin': '*',
            },
        },
        configureWebpack: {
            output: {
                library: `${name}-[name]`,
                libraryTarget: 'umd', // 把微应用打包成 umd 库格式
            },
        },
    
    })
    

    Vue2

    Vue2 和 Vue3 中不使用 Vite 是一样的,唯一的区别就是 Vue2 和 Vue3 的语法不太一样,直接上代码

    // main.js 
    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({
            base: window.__POWERED_BY_QIANKUN__ ? '/app-vue/' : '/',
            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;
    }
    

    打包配置修改

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

    这里只介绍了子应用为 Vue 的情况,当然我们也可以创建一个 React 或者 Angular 的子应用,其配置方法 qiankun 中都有示例

    相关文章

      网友评论

          本文标题:微前端 qiankun + Vite + Vue3 + Vue2

          本文链接:https://www.haomeiwen.com/subject/bbymrdtx.html