qiankun乾坤微前端爬坑

一、主应用

1、引用乾坤

    // package.json
    "qiankun": "^2.6.3",

2、主节点不能和子应用相同

子应用的节点基本叫做app,主应用就不能叫做app,否则会出错

    <div
        id="frontendApp"
    >
        <!-- <router-view

注意其他使用到的地方和样式都要跟着改过来

     #frontendApp{
<body>
    <div id="frontendApp"></div>
</body>
</html>
new Vue({
    el: '#frontendApp',
    router,
    store,
    render: h => h(App)

3、子应用配置

function genActiveRule(routerPrefix) {
    return location => location.pathname.startsWith(routerPrefix);
}

let config;
switch (process.env.NODE_ENV) {
case 'development':
    config = {
        apps: [
            {
                name: 'frontMicroApp', // 应用的名字
                entry: 'https://a.b.com',
                container: '#microAppContainer', // 容器名(此项目页面中定义的容器id,用于把对应的子应用放到此容器中)
                activeRule: genActiveRule('/frontMicroAppPath'), // 激活的路径
            },
        ],
    };
    break;
}

export default config;

4、添加容器

                        <div id="microAppContainer"></div>

5、乾坤开启

import { registerMicroApps, start } from 'qiankun';
import qiankunConfig from 'common/qiankun.js';


// ......
let app = null;
function render() {
    if (!app) {
        // eslint-disable-next-line no-new
        app = new Vue({
            el: '#frontendApp',
            router,
            store,
            render: h => h(App)
        });
    }
}

function initApp() {
    render();
}
initApp();

registerMicroApps(qiankunConfig.apps); // 注册应用
start({
    prefetch: false // 取消预加载
});// 开启

6、子应用事件通讯

import { initGlobalState } from 'qiankun';

//......

const actions = initGlobalState({ logout: false });
actions.onGlobalStateChange((state, prev) => {
    if (state.logout === true) {
        logOutHandler();
    }
});
function logOutHandler() {
    // do logout ... 
}

7、去掉冲突数据

1、去掉window.Vue

        // window.Vue = Vue;

8、接口代理

    '/frontMicroAppApi': {
        target: 'http://a.b.com',
        changeOrigin: true, // 是否跨域
        pathRewrite: {
            '^/frontMicroAppApi': '/api',
        }
    },

二、子应用

1、打包设置

webpack打包设置:(1)libraryTarget为umd;(2)library为和主应用商量好的名字;

  output: {
    library: 'frontMicroApp',
    libraryTarget: 'umd',

2、打包资源放到指定文件夹

正常打包资源放在static文件夹,这样多个应用资源路径就相同冲突了,每个应该根据项目定义文件名,不要定义为static。

outputDir: 'dist/appOneStatic',

同时记得清除项目中使用到static路径的地方,都要改动过来。

项目里public文件夹会直接拷贝到打包目录下,同样里面的资源文件夹也要更改,不要定义为static等;

3、开发环境允许跨域访问

devServer设置允许访问和允许跨域访问:(1)headers设置Access-Control-Allow-Origin;(2)disableHostCheck设置为true;

    headers: {
      // 因为qiankun内部请求都是fetch来请求资源,所以子应用必须允许跨域
      'Access-Control-Allow-Origin': '*'
    },
    disableHostCheck: true, // 为了把本地 localhost 映射到外网

4、接口请求加上统一前缀

子应用的请求都在主应用发起,所以所有子应用请求都要加上一个和主应用协商好的前缀。

主应用设置反向代理把这个前缀的请求转发到子应用。

建议在一个公共的地方设置,避免漏掉有的请求没有设置。也方便修改、管理等。

if (window.__POWERED_BY_QIANKUN__) {
  const qianKunPrefix = '/frontMicroAppApi';  // 和主应用的代理保持一致
 
  api = qianKunPrefix + api;
 
}

5、注册乾坤子应用

5.1、修改main.js,初始化路由和应用实例

  let router = null;
  let instance = null;
  function render(props) {
    // 初始化路由
    router = new Router({
        mode: 'history',
        base: '/frontMicroAppPath',
        routes: routes,
        scrollBehavior(to, from, savedPosition) {
        return { x: 0, y: 0 };
        },
        linkActiveClass: 'active',
    });
    // 初始化应用
    instance = new Vue({
      el: '#app',
      router,
      store,
      components: { App },
      template: '<App/>'
    });
  }

5.2、非乾坤时,独立运行

  if (!window.__POWERED_BY_QIANKUN__) { // 默认独立运行
    render();
  }

5.3、动态添加publicPath

  if (window.__POWERED_BY_QIANKUN__) { // 动态添加publicPath
    __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__; /* eslint-disable-line */
  }

5.4、子应用必须暴露三个接口:bootstrap、mount、unmount

  export async function bootstrap(props) {
  };
 
  export async function mount(props) {
    render(props);
  }
 
 
  export async function unmount(props) {
    instance.$destroy();
    instance.$el.innerHTML = '';
    instance = null;
    router = null;
  }

6、路由设置

6.1、base设置

添加一个base,和主应用协商好base路径,主应用根据base路径加载子应用。

if (window.__POWERED_BY_QIANKUN__) {
    new Router({
       base: '/frontMicroAppPath',
 
       ....
 
}

6.2、去掉*路径

避免子应用路径去影响到主应用的路径跳转,所以子应用的*路径配置要去掉。

代码逻辑里,默认先不添加,判断非乾坤环境再加上。

if (!window.__POWERED_BY_QIANKUN__) {
  routes.push({
      path: '*',
      redirect: '/home'
   })
}

6.3、实例化路由

在main.js的乾坤的render方法实例化路由

import routes from './router';
 
 
let router = null;
function render(props) {
  router = new Router({
    mode: 'history',
    base: '/frontMicroAppPath',
    routes: routes,
    scrollBehavior(to, from, savedPosition) {
      return { x: 0, y: 0 };
    },
    linkActiveClass: 'active',
  });
 
 
    ......
}

6.4、清空路由

在main.js的乾坤的unmount方法情况路由

 export async function unmount(props) {
     
    ......
    router = null;
 }

7、事件通讯

7.1、在main.js的mount方法中获得乾坤的全局状态

let qianKunProps = '';
 export async function mount(props) {
   qianKunProps = props;
   render(props);
 }

7.2、乾坤全局状态提供的事件通讯方法

onGlobalStateChange: (callback: OnGlobalStateChangeCallback, fireImmediately?: boolean) => void, 在当前应用监听全局状态,有变更触发 callback,fireImmediately = true 立即触发 callback
 
setGlobalState: (state: Record<string, any>) => boolean, 按一级属性设置全局状态,微应用中只能修改已存在的一级属性
 
offGlobalStateChange: () => boolean,移除当前应用的状态监听,微应用 umount 时会默认调用

7.3、登出通讯例子

这个事件通讯的原理类似于响应式,一个地方改变会通知到别的地方。

所以子应用和主应用了解清楚定义了哪些值用于监听事件。

例如主应用设置了监听logout值去调用登出方法:

import { initGlobalState } from 'qiankun';
 
const actions = initGlobalState({ logout: false });
actions.onGlobalStateChange((state, prev) => {
    if (state.logout === true) {
        logOutHandler();
    }
});

那么,子应用只需要改动logout的值,就能触发主应用的登出操作:

export function qianKunLogout() {
  if (window.__POWERED_BY_QIANKUN__ && qianKunProps && qianKunProps.setGlobalState) {
    qianKunProps.setGlobalState({
      logout: true,
    });
  }
}
import { qianKunLogout } from '@/main.js';
 
      if (window.__POWERED_BY_QIANKUN__) {
        qianKunLogout();
        return;
      }

8、注意点

8.1、主应用设置的name和子应用打包的library要对上

{
    name: 'frontMicroApp', // 应用的名字
    entry: '...', //
    container: '...',
    activeRule: genActiveRule('/...'),
},
output: {
  library: 'frontMicroApp', // 和主应用的name对应上
  libraryTarget: 'umd',
}

8.2、主应用的activeRule要和子应用路由的base对应上

{
    name: '...', // 应用的名字
    entry: '...', //
    container: '...',
    activeRule: genActiveRule('/frontMicroAppPath'),
},
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,492评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,048评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,927评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,293评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,309评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,024评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,638评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,546评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,073评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,188评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,321评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,998评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,678评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,186评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,303评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,663评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,330评论 2 358

推荐阅读更多精彩内容