什么是微前端?
一种将独立的前端应用组成一个更大的整体的架构风格。
假设你想构建一个渐进式的Web应用程序,但是你很难将新的功能实现于现有的整体应用中。比如你想开始使用新的 JS 语法(或TypeScript),但是你无法在现有的构建过程中使用对应的构建工具。又或者,你只想扩展你的开发团队,以便多个团队可以同时处理一个产品,但是现有应用中的耦合和复杂度让每个开发者互相掣肘。这些都是真实存在的问题,这些问题极大地降低了大型团队的开发效率。
最近,我们看到越来越多前端开始把注意力集中在复杂前端应用的架构上面。尤其是如何将前端整体分解,每一块可以独立开发、测试和部署,同时对用户而言仍是一个整体。这种技术就是微前端,
为什么使用微前端
为了将巨大的前端项目分离解耦。例如:1.如果每一个功能模块对应一个git仓库,那当我们需要用其中几个功能去做新的项目时,只需要引入对应的git库就可以完成。2.我们需要对某一个功能进行迭代升级,同时想引入ts代替原来的es6语法,又不对其他功能模块有冲突,那微前端同样可以完成。
单体应用对比前端微服务化:
普通的前端单体应用
微前端架构
优点:
1.应用自治。只需要遵循统一的接口规范或者框架,以便于系统集成到一起,相互之间是不存在依赖关系的。
2.单一职责。每个前端应用可以只关注于自己所需要完成的功能。
3.技术栈无关。你可以使用 Angular 的同时,又可以使用 React 和 Vue。
缺点:
1.应用的拆分基础依赖于基础设施的构建,一旦大量应用依赖于同一基础设施,那么维护变成了一个挑战。
2.拆分的粒度越小,便意味着架构变得复杂、维护成本变高。
3.技术栈一旦多样化,便意味着技术栈混乱
规避风险的使用微前端
1.规定统一代码风格
2.制定统一技术栈
3.对代码仓库拆分需要慎重规划,考虑到后续的迭代与维护
4.统一UI组件库,让一个系统内UI风格一致
技术方式
从技术实践上,微前端架构可以采用以下的几种方式进行:
1.路由分发式。通过 HTTP 服务器的反向代理功能,来将请求路由到对应的应用上。
前端微服务化。在不同的框架之上设计通讯、加载机制,以在一个页面内加载对应的应用。
2.微应用。通过软件工程的方式,在部署构建环境中,组合多个独立应用成一个单体应用。
3.微件化。开发一个新的构建系统,将部分业务功能构建成一个独立的 chunk 代码,使用时只需要远程加载即可。
4.前端容器化。通过将 iFrame 作为容器,来容纳其它前端应用。
5.应用组件化。借助于 Web Components 技术,来构建跨框架的前端应用。
技术实现
现在主要以single-spa为框架,可以根据技术栈使用vue、react、angular等js框架
Single-SPA的简单用法(以react为例)
1.创建一个HTML文件
<html>
<body>
<div id="root"></div>
<script src="single-spa-config.js"></script>
</body>
</html>
2.创建single-spa-config.js 文件
// single-spa-config.js
import * as singleSpa from 'single-spa';
// 加载react 项目的入口js文件 (模块加载)
const loadingFunction = () => import('./react/app.js');
// 当url前缀为 /react的时候.返回 true (底层路由)
const activityFunction = location => location.pathname.startsWith('/react');
// 注册应用
singleSpa.registerApplication('react', loadingFunction, activityFunction);
//singleSpa 启动
singleSpa.start();
3.封装React项目的渲染出口文件
我们把渲染react的入口文件修改成这样,便可接入到single-spa
import React from 'react'
import ReactDOM from 'react-dom'
import singleSpaReact from 'single-spa-react'
import RootComponent from './root.component'
if (process.env.NODE_ENV === 'development') {
// 开发环境直接渲染
ReactDOM.render(<RootComponent />, document.getElementById('root'))
}
//创建生命周期实例
const reactLifecycles = singleSpaReact({
React,
ReactDOM,
rootComponent: RootComponent
domElementGetter: () => document.getElementById('root')
})
// 项目启动的钩子
export const bootstrap = [
reactLifecycles.bootstrap,
]
// 项目启动后的钩子
export const mount = [
reactLifecycles.mount,
]
// 项目卸载的钩子
export const unmount = [
reactLifecycles.unmount,
]
当我们的浏览器url的前缀有/react的时候,程序就可以正常渲染这个应用
所以,所以我们这个react应用的所有路由前缀都得有 /react
总结
多年来,随着前端不断变复杂,我们看到了对更可扩展的体系结构日益增长的需求。我们应该能够通过独立的自治团队来开发软件。
虽然微前端不是唯一的办法,但我们已经看到了许多微前端达到这些目标的实际案例,并且随着时间的推移,我们已经能够逐渐将这项技术应用于旧网站。无论微型前端对你和你的团队是不是正确的方法,微前端都是一种趋势,在这种趋势下,前端工程化和前端体系结构都将变得越来越重要。