2022 你还不会微前端吗 (上) — 从巨石应用到微应用(一)

简介: 2022 你还不会微前端吗 (上) — 从巨石应用到微应用

image.png


前言

微前端系列分为 上/下 两篇,本文为 上篇 主要还是了解微前端的由来、概念、作用等,以及基于已有的微前端框架进行实践,并了解微前端的核心功能所在,而在下篇 2022 你还不会微前端吗 (下) — 揭秘微前端核心原理 中主要就是通过自定义实现一个微前端框架来加深理解。


微前端是什么?

微前端 是一种类似于 微服务 的概念,因此要想更好的了解微前端,就必须先了解一下微服务。

微服务

微服务架构 是将一个庞大的业务系统按照业务模块拆分成 若干个独立的子系统,每个子系统都是一个独立的应用,它是一种将应用构建成一系列按 业务领域 划分模块的、小的自治服务的软件架构方式,倡导将 复杂的单体应用 拆分成 若干个功能单一、松偶合的服务,目的是降低开发难度、增强扩展性、便于敏捷开发,及持续集成与交付活动。

image.png

与微服务相对的另一个概念是传统的 单体式应用程序( Monolithic application ),单体式应用内部包含了 所有需要的服务,且各个服务功能模块具有 强耦合性(相互依赖),导致难以进行拆分和扩容。

image.png

简单来说,单体式应用程序 其实就是一台服务器处理了需要所有的功能,微服务 就是将功能按照业务模块划分成了不同的独立服务,各个微服务间通过 HTTP 协议进行通信,通过注册中心观测微服务状态。

微服务 概念主要存在于后端开发,但这个概念是不是和你听说过的 微前端 很像了。

微前端

随着大前端的快速发展 和 SPA 的大规模应用,也带来了新的问题,而这些问题都催化出了 微前端 的概念:

  • 项目功能不断增多、体积不断增大(巨石应用),导致打包时间成正比例增长,是否能保证更好的 项目扩展
  • 前端技术更新太快,一个项目历经一两年也许就需要进行项目升级,甚至是切换技术栈,但仍需要老项目的代码,是否能进行 新老版本的兼容
  • 团队技术栈不一,又需要保证同一项目的开发,是否能保证不同团队的 独立开发
  • SPA 项目的任何变动都需执行完整的打包、部署,是否能保证不同内容 独立部署

image.png

微前端 是一种类似于 微服务 的架构,是一种由独立交付的 多个前端应用 组成整体的架构风格,将前端应用分解成一些更小、更简单的能够 独立开发、测试、部署 的应用,而对外表现仍是 单个内聚的产品

微前端框架

微前端框架的核心

一个微前端框架至少要保证如下的核心功能:

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

single-spa

single-spa 是一个将多个单页面应用聚合为一个整体应用的 JavaScript 微前端框架。

核心原理

基座 (主) 应用 中注册所有 App 的路由,single-spa 保存各子应用的路由映射关系,充当微前端控制器 Controler,当对应的 URL 变换时,除了匹配 基座应用 本身的路由外,还会匹配 子应用 路由并加载渲染子应用。

子应用会经过如下过程

  • 下载 (loaded)
  • 初始化 (initialized)
  • 挂载 (mounted)
  • 卸载 (unmounted)

single-spa 还会通过 生命周期 为这些过程提供对应的 钩子函数

qiankun

qiankun 是一个基于 single-spa微前端 实现库,目的是提供更简单、无痛的构建一个生产可用微前端架构系统。

包括在 single-spa 文档中也有推荐使用 qiankun

image.png

single-spa 实践

创建子应用

Vue3 子应用

为了快速的创建应用,这里通过 vue create vue3-micro-app 来快速创建技术栈为 Vue3子应用

以下在子应用中的处理方式可用 single-spa-vue 来简化

页面效果如下

image.png

子应用入口文件

为了子应用既可以独立运行,也可以在基座应用中运行,需要在子应用入口文件进行一些修改,具体如下:

  • 将原本的初始化内容封装在自定义的 render 函数中,目的是可以在不同的环境执行初始化操作
  • 若当前在基座应用中进行渲染,则其页面内容对应的挂载容器需要指定为基座容器中对应的 DOM 节点
  • window.singleVue3 不存在时意味着是子应用独立运行,此时直接按照原本的初始化方式进行即可,即直接调用 render() 函数
  • 子应用必须导出 bootstrap、mount、unmount 等生命周期函数,且其返回值类型要为 fullfilled 状态的 Promise,否则后续操作不会执行
  • 定义 instance 变量存储实例对象,方便在当前子应用在基座应用中被切换时可以执行真正的卸载子应用
// main.ts
import { createApp } from 'vue'
import type { App as AppType } from 'vue'
import App from './App.vue'
import router from './router'
let instance: AppType
function render(container?: string) {
    instance = createApp(App)
    instance.use(router).mount(container || '#micro-vue-app')
}
// 当 window.singleVue3 不存在时,意味着是子应用单独运行
if (!window.singleVue3) {
    render();
}
// 子应用必须导出 以下生命周期 bootstrap、mount、unmount
export const bootstrap = () => {
    return Promise.resolve()
};
export const mount = (props: any) => {
    render(props.container);
    return Promise.resolve()
};
export const unmount = () => {
    instance.unmount();
    return Promise.resolve()
};
复制代码

为什么要将 x.mount('#app') 换成 x.mount('#micro-vue-app') ?

如果你明白 子应用基座应用 中的渲染方式就不难理解了,因为当前这个子应用的挂载容器的 id="app" 而基座应用中的默认挂载容器也是 id="app",这显然会导致冲突,初始化渲染时会渲染基座应用本身,但是当你切换到 vue3 的子应用时,就会发现当前子应用的内容整个覆盖了基座应用的内容,因为此时子应用在进行挂挂载的时候,会把已经渲染 基座应用 的容器再一次作为 子应用 的容器进行渲染,于是内容就会被完全替换成子应用的内容。

基座应用被子应用替换效果如下:

image.png

路由配置

路由模式为 hash 模式,默认路由配置:

import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
import HomeView from '../views/HomeView.vue'
const routes: Array<RouteRecordRaw> = [
  {
    path: '/',
    name: 'home',
    component: HomeView
  },
  {
    path: '/about',
    name: 'about',
    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
  }
]
const router = createRouter({
  history: createWebHashHistory(),
  routes
})
export default router
复制代码

打包配置

vue.config.js 下必须将打包后的输出格式指定为 umd 格式:

module.exports = {
  configureWebpack: {
    output: {
      library: 'singleVue3',
      libraryTarget: 'umd',
      globalObject: 'window',
    },
    devServer: {
      port: 5000,
    },
  },
}
复制代码

React 子应用

类似的,这里通过 npx create-react-app react-micro-app 来快速创建技术栈为 React子应用

以下在子应用中的处理方式可用 single-spa-react 来简化

页面效果如下

image.png

子应用入口文件

此部分核心内容和上述的 vue3 子应用一致,不在额外说明,入口文件代码如下:

// index.js
import React from 'react'
import ReactDOM from 'react-dom/client'
import './index.css'
import App from './App'
let root = null
function render(props = {}) {
  const container = document.getElementById(
    props.container ? props.container.slice(1) : 'root',
  )
  if(!container) return
  root = ReactDOM.createRoot(container)
  root.render(
    <React.StrictMode>
      <App {...props} />
    </React.StrictMode>,
  )
}
// 当 window.singleReact 不存在时,意味着是子应用单独运行
if (!window.singleReact) {
  render()
}
// 子应用必须导出 以下生命周期 bootstrap、mount、unmount
export const bootstrap = () => {
  return Promise.resolve()
}
export const mount = (props) => {
  render(props)
  return Promise.resolve()
}
export const unmount = () => {
  root.unmount()
  return Promise.resolve()


目录
相关文章
|
6天前
|
前端开发 JavaScript 安全
前端性能调优:HTTP/2与HTTPS在Web加速中的应用
【10月更文挑战第27天】本文介绍了HTTP/2和HTTPS在前端性能调优中的应用。通过多路复用、服务器推送和头部压缩等特性,HTTP/2显著提升了Web性能。同时,HTTPS确保了数据传输的安全性。文章提供了示例代码,展示了如何使用Node.js创建一个HTTP/2服务器。
16 2
|
7天前
|
Rust 前端开发 JavaScript
前端性能革命:WebAssembly在高性能计算中的应用探索
【10月更文挑战第26天】随着Web应用功能的日益复杂,传统JavaScript解释执行模式逐渐成为性能瓶颈。WebAssembly(Wasm)应运而生,作为一种二进制代码格式,支持C/C++、Rust等语言编写的代码在浏览器中高效运行。Wasm不仅提升了应用的执行速度,还具备跨平台兼容性和安全性,显著改善了Web应用的响应速度和用户体验。
23 4
|
6天前
|
前端开发 数据管理 测试技术
前端自动化测试:Jest与Cypress的实战应用与最佳实践
【10月更文挑战第27天】本文介绍了前端自动化测试中Jest和Cypress的实战应用与最佳实践。Jest适合React应用的单元测试和快照测试,Cypress则擅长端到端测试,模拟用户交互。通过结合使用这两种工具,可以有效提升代码质量和开发效率。最佳实践包括单元测试与集成测试结合、快照测试、并行执行、代码覆盖率分析、测试环境管理和测试数据管理。
18 2
|
7天前
|
前端开发 安全 应用服务中间件
前端性能调优:HTTP/2与HTTPS在Web加速中的应用
【10月更文挑战第26天】随着互联网的快速发展,前端性能调优成为开发者的重要任务。本文探讨了HTTP/2与HTTPS在前端性能优化中的应用,介绍了二进制分帧、多路复用和服务器推送等特性,并通过Nginx配置示例展示了如何启用HTTP/2和HTTPS,以提升Web应用的性能和安全性。
14 3
|
7天前
|
前端开发 JavaScript 数据可视化
前端自动化测试:Jest与Cypress的实战应用与最佳实践
【10月更文挑战第26天】前端自动化测试在现代软件开发中至关重要,Jest和Cypress分别是单元测试和端到端测试的流行工具。本文通过解答一系列问题,介绍Jest与Cypress的实战应用与最佳实践,帮助开发者提高测试效率和代码质量。
21 2
|
7天前
|
前端开发 JavaScript API
前端框架新探索:Svelte在构建高性能Web应用中的优势
【10月更文挑战第26天】近年来,前端技术飞速发展,Svelte凭借独特的编译时优化和简洁的API设计,成为构建高性能Web应用的优选。本文介绍Svelte的特点和优势,包括编译而非虚拟DOM、组件化开发、状态管理及响应式更新机制,并通过示例代码展示其使用方法。
21 2
|
8天前
|
前端开发 JavaScript 开发者
“揭秘React Hooks的神秘面纱:如何掌握这些改变游戏规则的超能力以打造无敌前端应用”
【10月更文挑战第25天】React Hooks 自 2018 年推出以来,已成为 React 功能组件的重要组成部分。本文全面解析了 React Hooks 的核心概念,包括 `useState` 和 `useEffect` 的使用方法,并提供了最佳实践,如避免过度使用 Hooks、保持 Hooks 调用顺序一致、使用 `useReducer` 管理复杂状态逻辑、自定义 Hooks 封装复用逻辑等,帮助开发者更高效地使用 Hooks,构建健壮且易于维护的 React 应用。
20 2
|
13天前
|
JavaScript 前端开发 测试技术
前端全栈之路Deno篇(五):如何快速创建 WebSocket 服务端应用 + 客户端应用 - 可能是2025最佳的Websocket全栈实时应用框架
本文介绍了如何使用Deno 2.0快速构建WebSocket全栈应用,包括服务端和客户端的创建。通过一个简单的代码示例,展示了Deno在WebSocket实现中的便捷与强大,无需额外依赖,即可轻松搭建具备基本功能的WebSocket应用。Deno 2.0被认为是最佳的WebSocket全栈应用JS运行时,适合全栈开发者学习和使用。
|
9天前
|
前端开发 API UED
深入理解微前端架构:构建灵活、高效的前端应用
【10月更文挑战第23天】微前端架构是一种将前端应用分解为多个小型、独立、可复用的服务的方法。每个服务独立开发和部署,但共同提供一致的用户体验。本文探讨了微前端架构的核心概念、优势及实施方法,包括定义服务边界、建立通信机制、共享UI组件库和版本控制等。通过实际案例和职业心得,帮助读者更好地理解和应用微前端架构。
|
13天前
|
人工智能 资源调度 数据可视化
【AI应用落地实战】智能文档处理本地部署——可视化文档解析前端TextIn ParseX实践
2024长沙·中国1024程序员节以“智能应用新生态”为主题,吸引了众多技术大咖。合合信息展示了“智能文档处理百宝箱”的三大工具:可视化文档解析前端TextIn ParseX、向量化acge-embedding模型和文档解析测评工具markdown_tester,助力智能文档处理与知识管理。