美文网首页VUE学习
微前端 vue 实现

微前端 vue 实现

作者: 阿凯_8b27 | 来源:发表于2021-09-14 10:03 被阅读0次

    采用阿里的qiankun实现微前端快速构建

    1.利用vue-cli快速构建一个基础项目(基础项目也可以不用vue,这里是为了快速构建采用vue项目作为基础项目)

    vue init webpack
    npm install 
    

    2.下载qiankun

    npm install qiankun
    

    3.修改主入口index.html的id,改为container,防止和其他重复


    image.png

    4.修改main.js ,APP.vue

    <template>
      <div id="container">
        <!-- loading -->
        <div v-if="loading">loading</div>
        <!-- 子应用盒子 -->
        <div id="root-view" class="app-view-box" v-html="content"></div>
      </div>
    </template>
    
    <script>
    export default {
      name: 'App',
      props: {
        loading: Boolean,
        content: String
      }
    }
    </script>
    
    
    import Vue from 'vue'
    import App from './App.vue'
    import VueRouter from 'vue-router'
    import { registerMicroApps, setDefaultMountApp, start } from 'qiankun'
    const router = []
    
    Vue.use(VueRouter)
    Vue.config.productionTip = false
    let app = null
    /**
     * 渲染函数
     * appContent 子应用html内容
     * loading 子应用加载效果,可选
     */
    function render ({ appContent, loading } = {}) {
      if (!app) {
        app = new Vue({
          el: '#container',
          router,
          data () {
            return {
              content: appContent,
              loading
            }
          },
          render (h) {
            return h(App, {
              props: {
                content: this.content,
                loading: this.loading
              }
            })
          }
        })
      } else {
        app.content = appContent
        app.loading = loading
      }
    }
    
    /**
     * 路由监听
     * @param {*} routerPrefix 前缀
     */
    function genActiveRule (routerPrefix) {
      return location => location.pathname.startsWith(routerPrefix)
    }
    
    function initApp () {
      render({ appContent: '', loading: true })
    }
    
    initApp()
    
    // 传入子应用的数据
    let msg = {
      data: {
        auth: false
      },
      fns: [
        {
          name: '_LOGIN',
          _LOGIN (data) {
            console.log(`父应用返回信息${data}`)
          }
        }
      ]
    }
    // 注册子应用
    registerMicroApps(
      [
        {
          name: 'vue',
          entry: '//localhost:7101',
          render,
          activeRule: genActiveRule('/vue'),
          props: msg
        }
        // {
        //   name: 'sub-app-2',
        //   entry: '//localhost:8092',
        //   render,
        //   activeRule: genActiveRule('/app2')
        // }
      ],
      {
        beforeLoad: [
          app => {
            console.log('before load', app)
          }
        ], // 挂载前回调
        beforeMount: [
          app => {
            console.log('before mount', app)
          }
        ], // 挂载后回调
        afterUnmount: [
          app => {
            console.log('after unload', app)
          }
        ] // 卸载后回调
      }
    )
    
    // 设置默认子应用,与 genActiveRule中的参数保持一致
    setDefaultMountApp('/vue')
    
    // 启动
    start()
    

    去目录下构建一个vue项目
    修改新建项目的vue-config,记得这块端口需要和上面对应

    const path = require('path');
    const { name } = require('./package');
    
    function resolve(dir) {
      return path.join(__dirname, dir);
    }
    
    const port = 7101; // dev port
    
    module.exports = {
      /**
       * You will need to set publicPath if you plan to deploy your site under a sub path,
       * for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/,
       * then publicPath should be set to "/bar/".
       * In most cases please use '/' !!!
       * Detail: https://cli.vuejs.org/config/#publicpath
       */
      outputDir: 'dist',
      assetsDir: 'static',
      filenameHashing: true,
      // tweak internal webpack configuration.
      // see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md
      devServer: {
        // host: '0.0.0.0',
        hot: true,
        disableHostCheck: true,
        port,
        overlay: {
          warnings: false,
          errors: true,
        },
        headers: {
          'Access-Control-Allow-Origin': '*',
        },
      },
      // 自定义webpack配置
      configureWebpack: {
        resolve: {
          alias: {
            '@': resolve('src'),
          },
        },
        output: {
          // 把子应用打包成 umd 库格式
          library: `${name}-[name]`,
          libraryTarget: 'umd',
          jsonpFunction: `webpackJsonp_${name}`,
        },
      },
    };
    
    
    image.png

    在子项目中修改main.js 和追加public-path.js文件,里面有一些和主应用通信的方法

    import './public-path';
    import ElementUI from 'element-ui';
    import 'element-ui/lib/theme-chalk/index.css';
    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;
    
    Vue.use(ElementUI);
    
    let router = null;
    let instance = null;
    
    function render(props = {}) {
      const { container } = props;
      router = new VueRouter({
        base: window.__POWERED_BY_QIANKUN__ ? '/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();
    }
    
    function storeTest(props) {
      props.onGlobalStateChange &&
        props.onGlobalStateChange(
          (value, prev) => console.log(`[onGlobalStateChange - ${props.name}]:`, value, prev),
          true,
        );
      props.setGlobalState &&
        props.setGlobalState({
          ignore: props.name,
          user: {
            name: props.name,
          },
        });
    }
    
    export async function bootstrap() {
      console.log('[vue] vue app bootstraped');
    }
    
    export async function mount(props) {
      console.log('[vue] props from main framework', props);
      storeTest(props);
      render(props);
    }
    
    export async function unmount() {
      instance.$destroy();
      instance.$el.innerHTML = '';
      instance = null;
      router = null;
    }
    
    

    现在,子项目启动,再将主项目启动就可以了
    为了以后脚本方便维护
    可以加入 npm-run-all

        "start": "npm-run-all start:* ",
        "start:angluar": "cd angluar && start cmd /k npm start",
        "start:vue": "cd vue && start cmd /k npm start  "
    

    install,build同理加入
    未来也可以加入react,angluar,jq等作为子应用
    参考: https://qiankun.umijs.org/zh/guide

    相关文章

      网友评论

        本文标题:微前端 vue 实现

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