vue - qiankun微前端

微前端

  • 什么是微前端
    • 微前端架构具备以下几个核心价值:
    • 项目实践
      • 主应用

什么是微前端

Techniques, strategies and recipes for building a modern web app with multiple teams that can ship features independently. – Micro Frontends

微前端是一种多个团队通过独立发布功能的方式来共同构建现代化 web 应用的技术手段及方法策略。

微前端架构具备以下几个核心价值:

1.技术栈无关
主框架不限制接入应用的技术栈,微应用具备完全自主权

2.独立开发、独立部署
微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新

3.增量升级
在面对各种复杂场景时,我们通常很难对一个已经存在的系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的手段和策略

4.独立运行时
每个微应用之间状态隔离,运行时状态不共享
微前端架构具备以下几个核心价值:

项目实践

主应用

主应用不限技术栈,只需要提供一个容器 DOM,然后注册微应用并 start 即可。

先安装 qiankun :

$ yarn add qiankun # 或者 npm i qiankun -S

注册微应用并启动:

import { registerMicroApps, start } from 'qiankun';

registerMicroApps([
  {
    name: 'reactApp',
    entry: '//localhost:3000',
    container: '#container',
    activeRule: '/app-react',
  },
  {
    name: 'vueApp',
    entry: '//localhost:8080',
    container: '#container',
    activeRule: '/app-vue',
  },
  {
    name: 'angularApp',
    entry: '//localhost:4200',
    container: '#container',
    activeRule: '/app-angular',
  },
]);
// 启动 qiankun
start();

微应用分为有 webpack 构建和无 webpack 构建项目,有 webpack 的微应用(主要是指 Vue、React、Angular)需要做的事情有:

1.新增 public-path.js 文件,用于修改运行时的 publicPath。什么是运行时的 publicPath ?。
注意:运行时的 publicPath 和构建时的 publicPath 是不同的,两者不能等价替代。
2.微应用建议使用 history 模式的路由,需要设置路由 base,值和它的 activeRule 是一样的。
3.在入口文件最顶部引入 public-path.js,修改并导出三个生命周期函数。
4.修改 webpack 打包,允许开发环境跨域和 umd 打包。
主要的修改就是以上四个,可能会根据项目的不同情况而改变。例如,你的项目是 index.html 和其他的所有文件分开部署的,说明你们已经将构建时的 publicPath 设置为了完整路径,则不用修改运行时的 publicPath (第一步操作可省)。

Vue 微应用
以 vue-cli 3+ 生成的 vue 2.x 项目为例,vue 3 版本等稳定后再补充。

1.在 src 目录新增 public-path.js:

if (window.__POWERED_BY_QIANKUN__) {
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

2.入口文件 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__ ? '/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 { name } = require('./package');
module.exports = {
  devServer: {
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  },
  configureWebpack: {
    output: {
      library: `${name}-[name]`,
      libraryTarget: 'umd', // 把微应用打包成 umd 库格式
      jsonpFunction: `webpackJsonp_${name}`,
    },
  },
};
Angular 微应用
以 Angular-cli 9 生成的 angular 9 项目为例,其他版本的 angular 后续会逐渐补充。

在 src 目录新增 public-path.js 文件,内容为:

if (window.__POWERED_BY_QIANKUN__) {
  // eslint-disable-next-line no-undef
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
设置 history 模式路由的 base,src/app/app-routing.module.ts 文件:


+ import { APP_BASE_HREF } from '@angular/common';
@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
  // @ts-ignore
+  providers: [{ provide: APP_BASE_HREF, useValue: window.__POWERED_BY_QIANKUN__ ? '/app-angular' : '/' }]
})

3.修改入口文件,src/main.ts 文件。

import './public-path';
import { enableProdMode, NgModuleRef } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

if (environment.production) {
  enableProdMode();
}

let app: void | NgModuleRef<AppModule>;
async function render() {
  app = await platformBrowserDynamic()
    .bootstrapModule(AppModule)
    .catch((err) => console.error(err));
}
if (!(window as any).__POWERED_BY_QIANKUN__) {
  render();
}

export async function bootstrap(props: Object) {
  console.log(props);
}

export async function mount(props: Object) {
  render();
}

export async function unmount(props: Object) {
  console.log(props);
  // @ts-ignore
  app.destroy();
}

你可能感兴趣的:(工作笔记,前端,vue.js,javascript)