前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >微前端落地,乾坤小有乾坤

微前端落地,乾坤小有乾坤

作者头像
javascript艺术
发布2022-06-08 17:16:08
5930
发布2022-06-08 17:16:08
举报
文章被收录于专栏:javascript艺术javascript艺术
什么是微前端

通俗易懂的来说,微前端是可以将一个大应用的不同部分进行独立的部署,各个部分之间相互独立,独立部署的能力允许他们构建孤立或松散耦合的服务。即将单页面前端应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。

微前端的核心设计理念
  • 技术栈无关主框架不限制接入应用的技术栈,微应用具备完全自主权
  • 独立开发、独立部署微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新
  • 增量升级在面对各种复杂场景时,我们通常很难对一个已经存在的系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的手段和策略
  • 独立运行时每个微应用之间状态隔离,运行时状态不共享

微前端的核心目标是将巨石应用拆解成若干个可以独立的子应用

特性

📦 基于 single-spa 封装,提供了更加开箱即用的 API。 📱 技术栈无关,任意技术栈的应用均可 使用/接入,不论是 React/Vue/Angular/JQuery 还是其他等框架。 💪 HTML Entry 接入方式,让你接入微应用像使用 iframe 一样简单。 🛡 样式隔离,确保微应用之间样式互相不干扰。 🧳 JS 沙箱,确保微应用之间 全局变量/事件 不冲突。 ⚡️ 资源预加载,在浏览器空闲时间预加载未打开的微应用资源,加速微应用打开速度。 🔌 umi 插件,提供了 @umijs/plugin-qiankun 供 umi 应用一键切换成微前端架构系统。

qiankun快速上手

qiankun官网https://qiankun.umijs.org/zh/ 具体的代码示例 github上有一些qiankun的示例代码https://github.com/zhjing1019/QianKunDemo

F5-56FE-42CC-9E43-67CF1FF3C17E/appyinxiangcom/27675019/ENResource/p21

主应用

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

代码语言:javascript
复制
yarn add qiankun # 或者 npm i qiankun -S
代码语言:javascript
复制
import { registerMicroApps, start } from 'qiankun';

/**
 * 在主应用中注册微应用
 */
registerMicroApps([
    {
      // 必选,微应用的名称,微应用之间必须确保唯一
      name: 'vue sub-app1',
      // 必选,微应用的入口。
      entry: '//localhost:7100/sub.html',
      render,
      // 必选,微应用的激活规则。
      activeRule: genActiveRule('/sub-app1'),
      // loader - (loading: boolean) => void - 可选,loading 状态发生变化时会调用的方法。
      // props - object - 可选,主应用需要传递给微应用的数据。
      props: {
        test: 'test'
      }
    },
    {
      name: 'vue sub-app2',
      entry: '//localhost:7101',
      render,
      activeRule: genActiveRule('/sub-app2')
    },
    // { name: 'vue admin', entry: '//localhost:9428', render, activeRule: genActiveRule('/admin') },
  ],
  {
    // 主应用里生命周期的触发
    beforeLoad: [
      app => {
        console.log('before load', app);
      },
    ],
    beforeMount: [
      app => {
        console.log('before mount', app);
      },
    ],
    afterMount: [
      app => {
        console.log('after mount', app);
      },
    ],
    afterUnmount: [
      app => {
        console.log('after unload', app);
        app.render({appContent: '', loading: false});
      },
    ],
  },
  {
    fetch: request,
  },
);

start();

更多的API详请看官方文档:https://qiankun.umijs.org/zh/api

注册微应用

当微应用信息注册完之后,一旦浏览器的 url 发生变化,便会自动触发 qiankun 的匹配逻辑,所有 activeRule 规则匹配上的微应用就会被插入到指定的 container 中,同时依次调用微应用暴露出的生命周期钩子 微应用需要在自己的入口 js (通常就是你配置的 webpack 的 entry js) 导出 bootstrap、mount、unmount 三个生命周期钩子,以供主应用在适当的时机调用。微应用不需要额外安装任何其他依赖即可接入 qiankun 主应用。

代码语言:javascript
复制
/**
 * bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
 * 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
 */
export async function bootstrap() {
  console.log('react app bootstraped');
}

/**
 * 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
 */
export async function mount(props) {
  ReactDOM.render(<App />, props.container ? props.container.querySelector('#root') : document.getElementById('root'));
}

/**
 * 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
 */
export async function unmount(props) {
  ReactDOM.unmountComponentAtNode(
    props.container ? props.container.querySelector('#root') : document.getElementById('root'),
  );
}

/**
 * 可选生命周期钩子,仅使用 loadMicroApp 方式加载微应用时生效
 */
export async function update(props) {
  console.log('update props', props);
}
主应用和子应用项目通信

initGloabalState(state) 定义全局状态,并返回通信方法,官方建议在主应用使用,微应用通过 props 获取通信方法。

  • registerMicroApps
    • props - object - 可选,主应用需要传递给微应用的数据。

主应用

代码语言:javascript
复制
registerMicroApps([
    {
      name: 'vue sub-app1',
      entry: '//localhost:7100/sub.html',
      render,
      activeRule: genActiveRule('/sub-app1'),
      // loader - (loading: boolean) => void - 可选,loading 状态发生变化时会调用的方法。
      // props - object - 可选,主应用需要传递给微应用的数据。
      props: {
        test: 'test'
      }
    }
],
{
    // 主应用里生命周期的触发
    beforeLoad: [
      app => {
        console.log('before load', app);
      },
    ],
    beforeMount: [
      app => {
        console.log('before mount', app);
      },
    ],
    afterMount: [
      app => {
        console.log('after mount', app);
      },
    ],
    afterUnmount: [
      app => {
        console.log('after unload', app);
        app.render({appContent: '', loading: false});
      },
    ],
  },
)

在主应用的registerMicroApps中注册子应用时,向props里传递了test值,并且在主应用的生命周期里都能拿到props里传递的值

子应用

代码语言:javascript
复制
/**
 * 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
 */
export async function mount(props) {
  console.log('props from main framework', props);
  instance = new Vue({
    el: '#app',
    router,
    store,
    render: h => h(App)
  })
}
/**
 * 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
 */
export async function unmount(props) {
  console.log('update props', props);
  instance.$destroy();
  instance = null;
}

/**
 * 可选生命周期钩子,仅使用 loadMicroApp 方式加载微应用时生效
 */
export async function update(props) {
  console.log('update props', props);
}

在子应用的生命周期里就能拿到相应的props里的值

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

主应用:

代码语言:javascript
复制
import { initGlobalState, MicroAppStateActions } from 'qiankun';

// 初始化 state
const actions: MicroAppStateActions = initGlobalState(state);

actions.onGlobalStateChange((state, prev) => {
  // state: 变更后的状态; prev 变更前的状态
  console.log(state, prev);
});
actions.setGlobalState(state);
actions.offGlobalStateChange();

子应用

代码语言:javascript
复制
// 从生命周期 mount 中获取通信方法,使用方式和 master 一致
export function mount(props) {
  props.onGlobalStateChange((state, prev) => {
    // state: 变更后的状态; prev 变更前的状态
    console.log(state, prev);
  });

  props.setGlobalState(state);
}

具体的更多方法可参考官方API:https://qiankun.umijs.org/zh/api

js变量隔离

每个子应用都有相应的生命周期,同一时间内,只会有一个子应用的实例生效。js沙箱封装在qiankun的生命周期中。当一个子应用被销毁,其js沙箱也就被销毁。唯一不足的地方是,window的对象,无法隔离,最好不要绑定原型。

css污染

1、scoped(暂时解决方案:主应用的样式使用特殊class或者scoped) 2、主应用可以通过设置 prefixCls 的方式避免冲突 3、配置 webpack 修改 less 变量

代码语言:javascript
复制
{
  loader: 'less-loader',
+ options: {
+   modifyVars: {
+     '@ant-prefix': 'yourPrefix',
+   },
+   javascriptEnabled: true,
+ },
}

qiankun的具体详细解析源码 https://www.jianshu.com/p/db08174fa4fc?utm_campaign=shakespeare

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-04-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 javascript艺术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是微前端
  • 微前端的核心设计理念
  • 特性
  • qiankun快速上手
    • 主应用
      • 注册微应用
        • 主应用和子应用项目通信
          • js变量隔离
            • css污染
            相关产品与服务
            容器服务
            腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档