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

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

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

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

它在前端領(lǐng)域能解決一些特定的問題:

  • 中后臺系統(tǒng)中,有一些別的技術(shù)棧開發(fā)的歷史模塊,但是希望能夠在入口里集成進(jìn)來。
  • sass 類的前端應(yīng)用,業(yè)務(wù)比較復(fù)雜,可能模塊很多,希望能拆分成多個應(yīng)用獨立維護(hù),也能夠集成到一起。

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

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

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

single-spa

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

它做的事情就是注冊微應(yīng)用、監(jiān)聽 URL 變化,然后激活對應(yīng)的微應(yīng)用:

圖片

注冊一個微應(yīng)用是這樣的:

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()

要指定當(dāng) url 是什么的時候,去加載子應(yīng)用,怎么加載。

它要求子應(yīng)用的入口文件導(dǎo)出 bootstrap、mount、unmount 的生命周期函數(shù),也就是在加載完成、掛載前、卸載前執(zhí)行的邏輯。

比如 react 的子應(yīng)用:

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 變化的時候,加載、卸載對應(yīng)的子應(yīng)用。

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

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

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

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

qiankun

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

它解決了哪些問題呢?

我們一個個來看一下:

加載子應(yīng)用的資源的方式

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

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

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

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

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

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

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

比如這樣一段 html:

圖片

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

圖片

這樣也就不再需要開發(fā)者指定怎么去加載子應(yīng)用了,實現(xiàn)了解析 html 自動加載的功能。

這個功能的實現(xiàn)放在 import-html-entry 這個包里。

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

所以說,注冊 qiankun 應(yīng)用的時候就更簡單了一點,只要指定 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 還支持預(yù)加載,會在空閑的時候加載解析出的 script 和 style:

圖片

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

JS、CSS 沙箱

子應(yīng)用之間肯定要實現(xiàn)隔離,不能相互影響,也就是要實現(xiàn) JS 和 CSS 的隔離。

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

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

qiankun 實現(xiàn) window 隔離有三種思路:

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

這幾個實現(xiàn)思路都比較容易理解。

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

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

圖片

當(dāng)支持 Proxy,并且傳入的配置沒設(shè)置 loose,就會使用 Proxy 的方式。

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

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

不過這種還是實現(xiàn)性的,需要手動開啟:

圖片

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

圖片

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

此外,qiankun 還內(nèi)置了應(yīng)用間狀態(tài)管理的方案:

應(yīng)用間的狀態(tài)管理

多個子應(yīng)用、子應(yīng)用和主應(yīng)用之間自然有一些狀態(tài)管理的需求,qiankun 也實現(xiàn)了這個功能。

使用起來是這樣的:

主應(yīng)用里做全局狀態(tài)的初始化,定義子應(yīng)用獲取全局狀態(tài)的方法 getGlobalState 和全局狀態(tài)變化時的處理函數(shù) 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

子應(yīng)用里可以通過參數(shù)拿到 global state 的 get、set 方法:

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

}

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

子應(yīng)用里大概這樣寫:

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 會在跑子應(yīng)用之前在 window 沙箱設(shè)置 POWERED_BY_QIANKUN 的變量,如果有這個變量就不要直接渲染,在 mount 生命周期里做渲染,否則就直接渲染。

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

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

總結(jié)

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

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

single-spa 實現(xiàn)了路由切換的時候,對子應(yīng)用的加載、卸載。

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

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

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

責(zé)任編輯:姜華 來源: 神光的編程秘籍
相關(guān)推薦

2021-04-21 19:20:53

前端 容器應(yīng)用

2020-06-02 09:45:07

微前端組件代碼

2020-05-06 09:25:10

微前端qiankun架構(gòu)

2022-07-27 22:56:45

前端應(yīng)用緩存qiankun

2020-09-04 13:50:35

前端異常監(jiān)控代碼

2022-02-13 23:00:48

前端微前端qiankun

2022-09-07 21:31:19

微前端架構(gòu)iframe

2009-10-23 16:43:34

APC

2024-04-26 09:33:18

攜程實踐

2021-12-28 16:09:28

芯片

2009-08-06 17:05:07

2020-05-19 10:45:31

沙箱前端原生對象

2011-11-01 11:55:50

vforum2011vmware云計算

2013-12-18 09:41:01

思科SDBSoftware De

2023-08-18 10:22:24

2022-10-17 15:21:18

2022-01-24 12:38:58

Vite插件開發(fā)

2009-02-23 18:10:07

IDC虛擬化IT

2020-12-09 18:22:00

微前端微服務(wù)前端

2020-12-09 09:30:57

前端開發(fā)技術(shù)
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 中文字幕精品一区二区三区精品 | 嫩草影院网址 | 麻豆久久 | 欧美视频成人 | 欧美性区 | 久久精品二区 | 久久久www成人免费精品 | 中文字幕一区二区三区四区五区 | 亚洲电影第三页 | 免费黄篇| 久久国内精品 | 91免费在线看 | 中文字幕一区二区三区四区五区 | 99久久精品免费看国产免费软件 | 婷婷五月色综合香五月 | 免费在线观看一级毛片 | 在线一区二区三区 | 久久精品欧美一区二区三区麻豆 | 久久久久久免费毛片精品 | 亚洲国产成人精品久久 | 久久国产精品一区二区三区 | 国产欧美精品 | 欧美黄a | 色综合色综合色综合 | 性在线 | 国产欧美精品区一区二区三区 | 午夜精品一区二区三区在线播放 | 中文字幕精品一区 | 一级在线免费观看 | 日韩美女在线看免费观看 | 91精品国产91久久久久久密臀 | 精品1区2区3区4区 | 免费在线观看av网址 | 在线中文字幕视频 | 天堂资源 | 国产福利资源在线 | 日韩高清一区二区 | 91在线免费视频 | 久草新在线 | 久久精品国产久精国产 | 一区二区三区影院 |