成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

微前端方案 Qiankun 只是更完善的 Single-Spa

開發 前端
前端應用能夠單獨跑,也能被集成到另一個應用中跑,這種架構叫做微前端架構。它在解決跨技術棧的應用集成、大項目拆分的場景下是很有用的。

一個前端應用能夠單獨跑,也能被作為一個模塊集成到另一個應用里,這種架構方式就叫做微前端。

它在前端領域能解決一些特定的問題:

  • 中后臺系統中,有一些別的技術棧開發的歷史模塊,但是希望能夠在入口里集成進來。
  • sass 類的前端應用,業務比較復雜,可能模塊很多,希望能拆分成多個應用獨立維護,也能夠集成到一起。

跨技術棧的應用集成、大的項目拆分成獨立的小項目,這些是微前端解決的典型問題。

微前端的實現方案有很多,比較流行的是 single-spa 以及對它做了一層封裝的 qiankun。

今天我們就來了解下這兩個微前端實現方案:

single-spa

微前端的基本需求就是在 url 變化的時候,加載、卸載對應的子應用,single spa 就實現了這個功能。

它做的事情就是注冊微應用、監聽 URL 變化,然后激活對應的微應用:

圖片

注冊一個微應用是這樣的:

import { registerApplication } from 'single-spa';
registerApplication({
name: 'app',
app: () => {
loadScripts('./chunk-a.js');
loadScripts('./chunk-b.js');
return loadScripts('./entry.js')
}
activeWhen: '/appName'
})

singleSpa.start()

要指定當 url 是什么的時候,去加載子應用,怎么加載。

它要求子應用的入口文件導出 bootstrap、mount、unmount 的生命周期函數,也就是在加載完成、掛載前、卸載前執行的邏輯。

比如 react 的子應用:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './index.tsx'
export const bootstrap = () => {}
export const mount = () => {
ReactDOM.render(<App/>, document.getElementById('root'));
}
export const unmount = () => {}

這部分邏輯還可以簡化,single-spa 提供了和 react、vue、angular 等集成的包,可以直接用:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './index.tsx';
import singleSpaReact from 'single-spa-react';
const reactLifecycles = singleSpaReact({
React,
ReactDOM,
rootComponent: App
});

export const bootstrap = reactLifecycles.bootstrap;
export const mount = reactLifecycles.mount;
export const unmount = reactLifecycles.unmount;

這就是完成了微前端的基本需求,能夠在 url 變化的時候,加載、卸載對應的子應用。

但是 single spa 做的事情比較簡單,不夠完善,比如說:

  • 加載微應用的時候要指定加載哪些 js、css,如果子應用的打包邏輯發生了變化,這里也要跟著變
  • 一個頁面可能有多個子應用,之間會不會有樣式的沖突、JS 的沖突?
  • 多個子應用之間通信怎么處理?

這些都要使用 sigle-spa 的時候,自己去解決。

所以說 single-spa 并不夠完善,于是 qiankun 就出來了:

qiankun

qiankun 并不是新的微前端框架,它只是解決了 single-spa 沒解決的一些問題,是更完善的基于 single-spa 的微前端方案。

它解決了哪些問題呢?

我們一個個來看一下:

加載子應用的資源的方式

用 single-spa 的時候,要在注冊的時候指定如何加載子應用:

import { registerApplication } from 'single-spa';
registerApplication({
name: 'app',
app: () => {
loadScripts('./chunk-a.js');
loadScripts('./chunk-b.js');
return loadScripts('./entry.js')
}
activeWhen: '/appName'
})

一般我們會結合 SystemJS 來用,簡化加載的邏輯,但是依然要知道子應用有哪些資源要加載,子應用打包邏輯變了,這里加載的方式就要跟著變。

能不能把這個加載過程給自動化了呢?

比如我根據 url 加載子應用的 html,然后解析出其中的 JS、CSS,自動去加載。

qiankun 就是按照這個思路來解決的:

它會加載入口 html,解析出 scripts、styles 的部分,單獨去加載,而其余的部分,會做一些轉換之后放到 dom 里。

比如這樣一段 html:

圖片

qiankun 會把 head 部分轉換成 qiankun-head,把 script 部分提取出來自己加載,其余部分放到 html 里:

圖片

這樣也就不再需要開發者指定怎么去加載子應用了,實現了解析 html 自動加載的功能。

這個功能的實現放在 import-html-entry 這個包里。

single-spa 的實現叫做 Config Entry 或者 JS Entry,也就是要自己指定怎么加載子應用,而 qiankun 這種叫做 Html Entry,會自動解析 html 實現加載。

所以說,注冊 qiankun 應用的時候就更簡單了一點,只要指定 html 的地址就行:

import { registerMicroApps, start } from 'qiankun';
registerMicroApps([
{
name: 'vue app',
entry: '//localhost:7100',
container: '#container-vue',
activeRule: '/micro-vue'
},
{
name: 'react app',
entry: '//localhost:7101',
container: '#container-react',
activeRule: '/micro-react'
},
]);

start();

而且 qiankun 還支持預加載,會在空閑的時候加載解析出的 script 和 style:

圖片

除了實現了基于 html 的自動加載,qiankun 還實現了 JS 和 CSS 的沙箱:

JS、CSS 沙箱

子應用之間肯定要實現隔離,不能相互影響,也就是要實現 JS 和 CSS 的隔離。

single-spa 沒有做這方面的處理,而 qiankun 實現了這個功能。

JS 的隔離也就是要隔離 window 這個全局變量,其余的不會有啥沖突,本來就是在不同函數的作用域執行的。

qiankun 實現 window 隔離有三種思路:

  • 快照,加載子應用前記錄下 window 的屬性,卸載之后恢復到之前的快照。
  • diff,加載子應用之后記錄對 window 屬性的增刪改,卸載之后恢復回去。
  • Proxy,創建一個代理對象,每個子應用訪問到的都是這個代理對象。

這幾個實現思路都比較容易理解。

前兩種思路有個問題,就是不能同時存在多個子應用,不然會沖突。一般常用的還是第三種 Proxy 的思路。

在 qiankun 里有這樣的策略選擇邏輯:

圖片

當支持 Proxy,并且傳入的配置沒設置 loose,就會使用 Proxy 的方式。

而 CSS 的隔離就是使用 shadow dom 了,這是瀏覽器支持的特性,shadow root 下的 dom 的樣式是不會影響其他 dom 的。

當然,也有另一種策略,就是 scoped css 的思路,在 css 選擇器里加一個前綴,并且在 dom 上也加一個 ID。

不過這種還是實現性的,需要手動開啟:

圖片

在源碼里可以看到這兩種方式:

圖片

總之,JS、CSS 的隔離都有多種方案,可以通過配置來選擇。

此外,qiankun 還內置了應用間狀態管理的方案:

應用間的狀態管理

多個子應用、子應用和主應用之間自然有一些狀態管理的需求,qiankun 也實現了這個功能。

使用起來是這樣的:

主應用里做全局狀態的初始化,定義子應用獲取全局狀態的方法 getGlobalState 和全局狀態變化時的處理函數 onGlobalStateChange:

import { initGlobalState } from 'qiankun'
const initialState = {
user: {
name: 'guang'
}
}
const actions = initGlobalState(initialState)
actions.onGlobalStateChange((newState, prev) => {
for (const key in newState) {
initialState[key] = newState[key]
}
})
actions.getGlobalState = (key) => {
return key ? initialState[key] : initialState
}
export default actions

子應用里可以通過參數拿到 global state 的 get、set 方法:

export async function mount(props) {
const globalState = props.getGlobalState();
props.setGlobalState({user: {name: 'dong'}})

}

綜上,其實 qiankun 就是更完善一些的 signle-spa,通過 html entry 的方式解決了要手動加載子應用的各種資源的麻煩,通過沙箱實現了 JS、CSS 的隔離,還實現了全局的狀態管理機制。

子應用里大概這樣寫:

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
function render(props) {
const { container } = props;
ReactDOM.render(<App />, container ? container.querySelector('#root') : document.querySelector('#root'));
}

if (!window.__POWERED_BY_QIANKUN__) {
render({});
}
export async function bootstrap() {
console.log('[react16] react app bootstraped');
}
export async function mount(props) {
props.onGlobalStateChange((value, prev) => console.log(`[onGlobalStateChange - ${props.name}]:`, value, prev), true);
props.setGlobalState({
ignore: props.name,
user: {
name: props.name,
},
});
render(props);
}
export async function unmount(props) {
const { container } = props;
ReactDOM.unmountComponentAtNode(container ? container.querySelector('#root') : document.querySelector('#root'));
}

qiankun 會在跑子應用之前在 window 沙箱設置 POWERED_BY_QIANKUN 的變量,如果有這個變量就不要直接渲染,在 mount 生命周期里做渲染,否則就直接渲染。

還要指定靜態資源的加載地址,通過 webpack_public_path 的全局變量。

其余的就和 single-spa 差不多了。

總結

前端應用能夠單獨跑,也能被集成到另一個應用中跑,這種架構叫做微前端架構。它在解決跨技術棧的應用集成、大項目拆分的場景下是很有用的。

主流的微前端方案是 single-spa 以及基于 single-spa 的 qiankun:

single-spa 實現了路由切換的時候,對子應用的加載、卸載。

但是它不夠完善,沒有解決資源加載、沙箱、全局狀態管理的問題,而 qiankun 做的更完善了一些:

  • 基于 html 自動分析 js、css,自動加載,不需要開發者手動指定如何加載。
  • 基于快照、Proxy 的思路實現了 JS 隔離,基于 Shadow Dom 和 scoped css 的思路實現了 CSS 隔離。
  • 提供了全局狀態管理的機制。

所以說,qiankun 基于 single-spa,使用方式差不多,但是各方面的功能更完善一些。

責任編輯:姜華 來源: 神光的編程秘籍
相關推薦

2021-04-21 19:20:53

前端 容器應用

2020-06-02 09:45:07

微前端組件代碼

2020-05-06 09:25:10

微前端qiankun架構

2022-07-27 22:56:45

前端應用緩存qiankun

2020-09-04 13:50:35

前端異常監控代碼

2022-02-13 23:00:48

前端微前端qiankun

2022-09-07 21:31:19

微前端架構iframe

2009-10-23 16:43:34

APC

2024-04-26 09:33:18

攜程實踐

2009-08-06 17:05:07

2021-12-28 16:09:28

芯片

2020-05-19 10:45:31

沙箱前端原生對象

2011-11-01 11:55:50

vforum2011vmware云計算

2023-08-18 10:22:24

2013-12-18 09:41:01

思科SDBSoftware De

2022-01-24 12:38:58

Vite插件開發

2022-10-17 15:21:18

2009-02-23 18:10:07

IDC虛擬化IT

2020-12-09 18:22:00

微前端微服務前端

2020-12-09 09:30:57

前端開發技術
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 中文字幕日韩欧美 | 免费黄色a视频 | 精品美女视频在免费观看 | 久热久热 | a视频在线| 99这里只有精品视频 | 日日综合| 免费观看日韩精品 | 欧美成人影院在线 | 日韩在线一区二区 | 亚洲高清在线播放 | 在线观看国产精品视频 | 亚洲欧美另类在线 | www日本高清 | 国产日韩一区二区三免费高清 | 国产色| 在线视频一区二区 | 波多野结衣精品 | 91精品国产综合久久久久久漫画 | 久草网站| 亚洲综合天堂 | 久久久久久久国产 | 成人免费视频久久 | 日日操夜夜操天天操 | 久久国产精品一区 | 国产在线视频三区 | 日韩精品区 | 五月综合激情在线 | 欧美精品一区三区 | 亚洲精品一区在线 | 欧美成人精品一区二区三区 | 一区二区三区四区在线免费观看 | 成人不卡 | 一级少妇女片 | 精品日韩一区二区 | 欧美视频成人 | 一区二区福利视频 | 亚洲人人舔人人 | 理论片免费在线观看 | 天天久久 | 国产精品久久久久久久久图文区 |