微前端是一種軟件架構藤树,可以將前端應用拆解成一些更小的能夠獨立開發(fā)部署的微型應用疫铜,然后再將這
些微應用進行組合使其成為整體應用的架構模式压彭。
微前端架構類似于組件架構闻妓,但不同的是菌羽,組件不能獨立構建和發(fā)布,但是微前端中的應用是可以的由缆。
微前端架構與框架無關注祖,每個微應用都可以使用不同的框架。
使用場景:
1.拆分巨型應用均唉,使應用變得更加可維護
2.兼容歷史應用是晨,實現(xiàn)增量開發(fā)
微前端實現(xiàn)
-
多個微應用如何組合
在微前端架構中,除了存在多個微應用以外舔箭,還存在一個容器應用罩缴,每個微應用都需要被注冊到容
器應用中蚊逢。
微前端中的每個應用在瀏覽器中都是一個獨立的 JavaScript 模塊,通過模塊化的方式被容器應用啟
動和運行箫章。
使用模塊化的方式運行應用可以防止不同的微應用在同時運行時發(fā)生沖突烙荷。 -
在微應用中如何實現(xiàn)路由
在微前端架構中,當路由發(fā)生變化時檬寂,容器應用首先會攔截路由的變化终抽,根據(jù)路由匹配微前端應
用,當匹配到微應用以后桶至,再啟動微應用路由昼伴,匹配具體的頁面組件。 -
微應用與微應用之間如何實現(xiàn)狀態(tài)共享
在微應用中可以通過發(fā)布訂閱模式實現(xiàn)狀態(tài)共享塞茅,比如使用 RxJS亩码。 -
微應用與微應用之間如何實現(xiàn)框架和庫的共享
通過 import-map 和 webpack 中的 externals 屬性。
Systemjs 模塊化解決方案
在微前端架構中野瘦,微應用被打包為模塊描沟,但瀏覽器不支持模塊化,需要使用 systemjs 實現(xiàn)瀏覽器中的模
塊化鞭光。
systemjs 是一個用于實現(xiàn)模塊化的 JavaScript 庫吏廉,有屬于自己的模塊化規(guī)范。
在開發(fā)階段我們可以使用 ES 模塊規(guī)范惰许,然后使用 webpack 將其轉換為 systemjs 支持的模塊
通過 webpack 將 react 應用打包為 systemjs 模塊席覆,在通過 systemjs 在瀏覽器中加載模塊
微前端框架single-spa
single-spa 是一個實現(xiàn)微前端架構的框架
在 single-spa 框架中有三種類型的微前端應用:
1.single-spa-application / parcel:微前端架構中的微應用,可以使用 vue汹买、react佩伤、angular 等框
架。(single-spa-application與路由關聯(lián) single-spa-parcel不與路由相關聯(lián)晦毙,主要用于跨應用共享ui組件)
2.single-spa root config:創(chuàng)建微前端容器應用生巡。
3.utility modules:公共模塊應用,非渲染組件见妒,用于跨應用共享 javascript 邏輯的微應用孤荣。
創(chuàng)建容器應用
- 安裝single-spa腳手架工具:npm install create-single-spa@2.0.3 -g
- 創(chuàng)建微前端應用目錄:mkdir spa_workspace && cd "$_"
- 創(chuàng)建微前端容器應用:create-single-spa
- 應用文件夾名稱:container
- 應用選擇 single-spa root config
- 組織名稱:test
組織名稱可以理解為團隊名稱,微前端架構允許多團隊共同開發(fā)應用须揣,組織名稱可以標識應用由哪個團隊開發(fā)盐股。
應用名稱的命名規(guī)則為 @組織名稱/應用名稱,比如 @test/todos
4.啟動應用 npm start
- 訪問應用 localhost:9000
root-config.js
import { registerApplication, start } from "single-spa"
/*注冊微前端應用 1. name: 字符串類型, 微前端應用名稱 "@組織名稱/應用名稱"
2. app: 函數(shù)類型, 返回 Promise, 通過 systemjs 引用打包好的微前端應用模塊代碼 (umd)
3. activeWhen: 路由匹配時激活應用
*/
registerApplication({
name: "@single-spa/welcome",
app: () => System.import( "https://unpkg.com/single-spa-welcome/dist/single-spa-welcome.js" ),
activeWhen: ["/"]
})
// start 方法必須在 single spa 的配置文件中調用
// 在調用 start 之前, 應用會被加載, 但不會初始化, 掛載或卸載.
start({
// 是否可以通過 history.pushState() 和 history.replaceState() 更改觸發(fā) single-spa 路由
// true 不允許 false 允許
urlRerouteOnly: true
})
index.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Root Config</title>
<!--
Remove this if you only support browsers that support async/await.
This is needed by babel to share largeish helper code for compiling async/await in older
browsers. More information at https://github.com/single-spa/create-single-spa/issues/112
-->
<script src="https://cdn.jsdelivr.net/npm/regenerator-runtime@0.13.7/runtime.min.js"></script>
<!--
This CSP allows any SSL-enabled host and for arbitrary eval(), but you should limit these directives further to increase your app's security.
Learn more about CSP policies at https://content-security-policy.com/#directive
-->
<meta http-equiv="Content-Security-Policy" content="default-src 'self' https: localhost:*; script-src 'unsafe-inline' 'unsafe-eval' https: localhost:*; connect-src https: localhost:* ws://localhost:*; style-src 'unsafe-inline' https:; object-src 'none';">
<meta name="importmap-type" content="systemjs-importmap" />
<!-- If you wish to turn off import-map-overrides for specific environments (prod), uncomment the line below -->
<!-- More info at https://github.com/joeldenning/import-map-overrides/blob/master/docs/configuration.md#domain-list -->
<!-- <meta name="import-map-overrides-domains" content="denylist:prod.example.com" /> -->
<!-- Shared dependencies go into this import map. Your shared dependencies must be of one of the following formats:
1. System.register (preferred when possible) - https://github.com/systemjs/systemjs/blob/master/docs/system-register.md
2. UMD - https://github.com/umdjs/umd
3. Global variable
More information about shared dependencies can be found at https://single-spa.js.org/docs/recommended-setup#sharing-with-import-maps.
-->
<script type="systemjs-importmap">
{
"imports": {
"single-spa": "https://cdn.jsdelivr.net/npm/single-spa@5.9.0/lib/system/single-spa.min.js"
}
}
</script>
<link rel="preload" as="script">
<!-- Add your organization's prod import map URL to this script's src -->
<!-- <script type="systemjs-importmap" src="/importmap.json"></script> -->
<% if (isLocal) { %>
<script type="systemjs-importmap">
{
"imports": {
"@study/root-config": "http://localhost:9000/study-root-config.js"
}
}
</script>
<% } %>
<!--
If you need to support Angular applications, uncomment the script tag below to ensure only one instance of ZoneJS is loaded
Learn more about why at https://single-spa.js.org/docs/ecosystem-angular/#zonejs
-->
<!-- <script src="https://cdn.jsdelivr.net/npm/zone.js@0.11.3/dist/zone.min.js"></script> -->
<script src="https://cdn.jsdelivr.net/npm/import-map-overrides@2.2.0/dist/import-map-overrides.js"></script>
<% if (isLocal) { %>
<script src="https://cdn.jsdelivr.net/npm/systemjs@6.8.3/dist/system.js"></script>
<script src="https://cdn.jsdelivr.net/npm/systemjs@6.8.3/dist/extras/amd.js"></script>
<% } else { %>
<script src="https://cdn.jsdelivr.net/npm/systemjs@6.8.3/dist/system.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/systemjs@6.8.3/dist/extras/amd.min.js"></script>
<% } %>
</head>
<body>
<main></main>
<!-- 導入微前端容器應用 -->
<script>
System.import('@study/root-config');
</script>
<!--import-map-overrides 可以覆蓋導入映射 當前項目中用于配合 single-spa Inspector 調試工具使用. 可以手動覆蓋項目中的 JavaScript 模塊加載地址, 用于調試. -->
<import-map-overrides-full show-when-local-storage="devtools" dev-libs></import-map-overrides-full>
</body>
</html>