前端技术笔记|微前端(qiankun)在非 webpack 构建的项目LayUI(主应用)中初体验

525 阅读1分钟

引入qiankun文件

<script src="https://unpkg.com/qiankun@2.7.0/dist/index.umd.min.js"></script>

在主应用中注册微应用

<script>
     var state = {};
     var actions = null;
     window.qiankun.registerMicroApps(
       [
         {
           name: "imap-frontend",
           entry: "/localhost:7101/imap/",
           // entry: "/imap/",
           container: "#image-map",
           activeRule: "/index",
         },
       ],
       {
         beforeLoad: [
           function (app) {
             console.log("[LifeCycle] before load %c%s", "color: green;", app.name);
           },
         ],
         beforeMount: [
           function (app) {
             console.log("[LifeCycle] before mount %c%s", "color: green;", app.name);
           },
         ],
         afterUnmount: [
           function (app) {
             console.log("[LifeCycle] after unmount %c%s", "color: green;", app.name);
           },
         ],
       }
     );
     window.qiankun.setDefaultMountApp("/index");
     window.qiankun.start();
     window.qiankun.runAfterFirstMounted(function () {
       console.log("[MainApp] first app mounted");
     });
   </script>

container 为主应用中用于显示微应用的容器的节点的选择器或者 Element 实例。

微应用中导出相应的生命周期钩子

  1. 在 src 目录新增 public-path.js
if (window.__POWERED_BY_QIANKUN__) {
 __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
  1. 入口文件 main.js 修改,为了避免根 id #app 与其他的 DOM 冲突,需要限制查找范围。
import './public-path';
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__ ? '/imap/' : '/imap/',
    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;
}
  1. 打包配置修改(vue.config.js):
const { name } = require('./package');
module.exports = {
  publicPath:"/imap/",
  outputDir: "imap",
  assetsDir: "static",
  filenameHashing: true,
  devServer: {
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  },
  configureWebpack: {
    output: {
      library: `${name}-[name]`,
      libraryTarget: 'umd', // 把微应用打包成 umd 库格式
      jsonpFunction: `webpackJsonp_${name}`,
    },
  },
};

主应用如何定义全局状态与微应用通信

  • 主应用定义全局状态
var state = {};
var actions = null;
actions = window.qiankun.initGlobalState(state);
actions.onGlobalStateChange(function (state, prev) {
    // state: 变更后的状态; prev 变更前的状态
    console.log(state, prev);
});
state.token = window.localStorage.getItem("TOKEN");
actions.setGlobalState(state);
actions.offGlobalStateChange();
  • 微应用监听 在main.js中的mount生命周期可获取通信数据,onGlobalStateChange可设置第二个参数立即触发监听;vue项目中可在监听到数据后设置vuex中,并使用计算属性(computed)与watch实现页面数据实时刷新。
export async function mount(props) {
  console.log("[vue] props from main framework", props);
  props.onGlobalStateChange((state, _prev) => {
    console.log(state.token)
  }, true);
  render(props);
}

线上部署Nginx配置

server {
        listen       8080;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   html/poject;
            index  index.html index.htm;
        }

        location /imap {
            alias   html/poject/imap;
            try_files $uri $uri/ /imap/index;
        }

        location /api {
            proxy_pass https://www.xxx.com/api/;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header   Cookie $http_cookie;
            proxy_set_header HTTP-X-REQUESTED-WITH $http_x_requested_with;
            proxy_set_header HTTP_X_REQUESTED_WITH $http_x_requested_with;
            proxy_set_header x-requested-with $http_x_requested_with;
        }
    }

目前线上存在问题,单独访问项目的时候刷新页面出现500, 有知道的大佬解决方法的还请留言帮助哦~