微前端 Micro-Frontnds - Single-SPA Application API
微前端 Micro-Frontnds - Single-SPA Application API
import { registerApplication, start } from 'single-spa';
// or
import * as singleSpa from 'single-spa';
registerApplication
使用在 root config 中,用於註冊應用
Simple arguments
singleSpa.registerApplication(
'app-name',
() => System.import('appName'),
location => location.pathname.startsWith('app')
)
Arguments
- appName: string 應用的名稱
- applicationOrLoadingFn:() => <Function | Promise> 一個返回應用或 Promise 的函式
- activeFn: (location) => boolean 純函式,以 window.location 為引數,返回true 表示啟用該應用,false 表示解除安裝該應用
- customProps?: Object | () => Object 可選,需要傳遞給應用生命週期鉤子的自定義引數
Configuration Object
singleSpa.registerApplication({
name: 'app-name',
app: () => System.import('appName'),
activeWhen: '/app',
customProps: {
authToken: 'xxxxx'
}
})
Arguments
- name: string 應用的名稱
- app: Application | () => Application | Promise 應用
- activeWhen: string | (location) => boolean | (string | (location) => boolean)[] 什麼時候啟用應用與上面的一樣
- customProps?: Object | () => Object 可選,需要傳遞給應用生命週期鉤子的自定義引數
start
讓 single-spa 對應用進行控制,讓您可以控制單頁應用程式的效能
singleSpa.start()
singleSpa.start({
urlRerouteOnly: true
})
Arguments
一個可選的物件,這個物件有 urlRerouteOnly 屬性
urlRerouteOnly:一個預設為false的布林值。如果設定為true,則除非更改了客戶端路由,否則對history.pushState()和history.replaceState()的呼叫將不會觸發單spa重新路由。在某些情況下,將此值設定為true可能會更好。
triggerAppChange
手動觸發 single-spa 載入應用
singleSpa.triggerAppChange();
navigatToUrl
在已註冊的應用之間執行 url 導航,而不需要處理 event.preventDefault() pushState triggerAppChange
// Three ways of using navigateToUrl
singleSpa.navigateToUrl("/new-url");
singleSpa.navigateToUrl(document.querySelector('a'));
document.querySelector('a').addEventListener(singleSpa.navigateToUrl);
Arguments
navigationObj: string | context | DOMEvent
- url 字串
- 帶有 href 屬性的標籤,例如 a 標籤
- 一個具有href屬性的DOMElement上的click事件的DOMEvent物件;
getMountedApps
獲取掛載(MOUNTED)應用的名字,返回一個字串陣列
const mountedAppNames = singleSpa.getMountedApps();
console.log(mountedAppNames); // ['app1', 'app2', 'navbar']
getAppNames
獲取所有註冊的應用,與應用的狀態無關
const appNames = singleSpa.getAppNames();
console.log(appNames); // ['app1', 'app2', 'app3', 'navbar']
getAppStatus
獲取指定應用的狀態
const status = singleSpa.getAppStatus('app1');
console.log(status); // one of many statuses (see list below). e.g. MOUNTED
Arguments
appName: string 註冊應用的名字
Returns
appStatus: string | null , null 表示應用不存在
- NOT_LOADEDapp :應用已經註冊,但是還沒有載入好
- LOADING_SOURCE_CODE:已經獲取到原始碼
- NOT_BOOTSTRAPPED: 應用已經載入好,但是還沒開始初始化
- BOOTSTRAPPING:已經呼叫 bootstrap 生命週期鉤子,但是還沒執行完
- NOT_MOUNTED:已經執行好 bootstrap ,但是還沒掛載
- MOUNTING:正在執行 mount 鉤子
- MOUNTED:應用已經掛載在 DOM 上了
- UNMOUNTING:正在執行 unmount
- UNLOADING:正在執行 unloading
- SKIP_BECAUSE_BROKEN:應用在載入,引導,安裝或解除安裝期間引發了錯誤,並且由於行為不當而被跳過,因此已被隔離。其他應用將繼續正常執行。
- LOAD_ERROR:應用在 loading 方法中返回了 reject 的 Promise,這通常是由於嘗試下載應用程式的JavaScript軟體包的網路錯誤。
unloadApplication
解除安裝已註冊的應用程式的目的是將其設定回NOT_LOADED狀態,這意味著它將在下次需要安裝時重新引導。這樣做的主要用例是允許熱過載整個已註冊的應用程式,但是無論何時您要重新引導應用程式,unloadApplication都會很有用。
// Unload the application right now, without waiting for it to naturally unmount.
singleSpa.unloadApplication('app1');
// Unload the application only after it naturally unmounts due to a route change.
singleSpa.unloadApplication('app1', {waitForUnmount: true});
當呼叫 unloadApplication 後 Single-spa 會執行如下幾步
1. 在要解除安裝的註冊應用程式上呼叫解除安裝生命週期。
2. 設定 App 狀態為 NOT_LOADED
3. 觸發重新路由,在這期間 single-spa 會掛載剛解除安裝的應用
因為呼叫unloadApplication時可能會掛載已註冊的應用程式,所以您可以指定是要立即解除安裝還是要等待直到不再掛載該應用程式。這是通過waitForUnmount選項完成的。
Arguments
appName: string 應用名稱
Options?: { waitForUnmoun: boolean = false} 可選物件引數,預設 single-spa 會立即解除安裝指定應用,如果設定為 true,single-spa 會等應用不處於 MOUNTED 狀態的時候進行解除安裝。
unregisterApplication
unregisterApplication函式將解除安裝,解除安裝和登出應用程式,一旦呼叫,應用不會再掛載
import { unregisterApplication } from 'single-spa';
unregisterApplication('app1').then(() => {
console.log('app1 is now unmounted, unloaded, and no longer registered!');
})
- Unregistering 應用程式不會將其從SystemJS模組登錄檔中刪除。
- Unregistering 應用程式不會從瀏覽器記憶體中刪除其程式碼或javascript框架。
- Unregistering 應用程式的另一種方法是在應用程式的活動功能內執行許可權檢查。這具有防止應用程式掛載的類似效果。
Arguments
appName: string 應用名稱
checkActivityFunctions
將使用模擬視窗位置呼叫每個應用程式的活動函式,並提供應在該位置掛載哪些應用程式的列表。
const appsThatShouldBeActive = singleSpa.checkActivityFunctions();
console.log(appsThatShouldBeActive); // ['app1']
const appsForACertainRoute = singleSpa.checkActivityFunctions({pathname: '/app2'});
console.log(appsForACertainRoute); // ['app2']
Arguments
mockWindowLocation: string 表示window.location的字串,將在呼叫每個應用程式的活動函式以測試它們是否返回true時使用。
Returns
appNames: string[] 返回符合的應用名稱的陣列
addErrorHandler
在生命週期函式或者啟用函式中報錯的時候會執行該方法,如果沒有這個處理函式,就會直接丟擲到視窗
singleSpa.addErrorHandler(err => {
console.log(err);
console.log(err.appOrParcelName);
console.log(singleSpa.getAppStatus(err.appOrParcelName));
});
Arguments
errorHandler: Function(error: Error) 將通過Error物件呼叫,該物件還具有message和appOrParcelName屬性。
removeErrorHandler
移除錯誤處理函式
singleSpa.addErrorHandler(handleErr)
singleSpa.removeErrorHandler(handleErr)
function handleErr(err) {
console.log(err)
}
Arguments
errorHandler: Function 函式名稱
Returns
Boolean :true 表示移除成功
mountRootParcel
建立並掛載一個 singel-spa parcel
// Synchronous mounting
const parcel = singleSpa.mountRootParcel(parcelConfig, {prop1: 'value1', domElement: document.getElementById('a-div')});
parcel.mountPromise.then(() => {
console.log('finished mounting the parcel!')
})
// Asynchronous mounting. Feel free to use webpack code splits or SystemJS dynamic loading
const parcel2 = singleSpa.mountRootParcel(() => import('./some-parcel.js'), {prop1: 'value1', domElement: document.getElementById('a-div')});
Arguments
parcelConfig: object | loading Function
parcelProps: object 具有 DOM 元素屬性的物件
returns
Parcel object
pathToActiveWhen
pathToActiveWhen 函式將字串URL路徑轉換為活動函式。字串路徑可能包含 single-spa 匹配任何字元的路由引數。假定提供的字串是字首。
當在註冊應用的時候給 ativeWhen 傳遞一個字串時會被呼叫
Arguments
Path: string url 的字首
returns: (location: location) => boolean
Examples
let activeWhen = singleSpa.pathToActiveWhen('/settings');
activewhen(new URL('http://localhost/settings')); // true
activewhen(new URL('http://localhost/settings/password')); // true
activeWhen(new URL('http://localhost/')); // false
activeWhen = singleSpa.pathToActiveWhen('/users/:id/settings');
activewhen(new URL('http://localhost/users/6f7dsdf8g9df8g9dfg/settings')); // true
activewhen(new URL('http://localhost/users/1324/settings')); // true
activewhen(new URL('http://localhost/users/1324/settings/password')); // true
activewhen(new URL('http://localhost/users/1/settings')); // true
activewhen(new URL('http://localhost/users/1')); // false
activewhen(new URL('http://localhost/settings')); // false
activeWhen(new URL('http://localhost/')); // false
activeWhen = singleSpa.pathToActiveWhen('/page#/hash');
activeWhen(new URL('http://localhost/page#/hash')); // true
activeWhen(new URL('http://localhost/#/hash')); // false
activeWhen(new URL('http://localhost/page')); // false
ensureJQuerySupport
用於保障不同版本的 jQuery 的 event delegation
Arguments
jQuery? : JQueryFn = window.jQuery 對jQuery已繫結到的全域性變數的引用
setBootstrapMaxTime
設定全域性 bootstrap 的超時時間
// After three seconds, show a console warning while continuing to wait.
singleSpa.setBootstrapMaxTime(3000);
// After three seconds, move the application to SKIP_BECAUSE_BROKEN status.
singleSpa.setBootstrapMaxTime(3000, true);
// don't do a console warning for slow lifecycles until 10 seconds have elapsed
singleSpa.setBootstrapMaxTime(3000, true, 10000);
Arguments
Mills: number 超時之前等待 bootstrap 完成的毫秒數。
dieOnTimeout: boolean = false 如果為false,則已註冊的應用程式會使速度降低,直到達到 mills 之前,只會在控制檯中引起一些警告。如果為true,則使已註冊應用程式將被置為 SKIP_BECAUSE_BROKEN 狀態,在此狀態下,它們將再也沒有機會改變內容。
warningMillis: number = 1000 在最終超時之前發生的控制檯警告之間等待的毫秒數。
setMountMaxTime
設定全域性 mount 的超時時間
// After three seconds, show a console warning while continuing to wait.
singleSpa.setMountMaxTime(3000);
// After three seconds, move the application to SKIP_BECAUSE_BROKEN status.
singleSpa.setMountMaxTime(3000, true);
// don't do a console warning for slow lifecycles until 10 seconds have elapsed
singleSpa.setMountMaxTime(3000, true, 10000);
Arguments
同上
setUnmountMaxTime
設定全域性 unmount 的超時時間
// After three seconds, show a console warning while continuing to wait.
singleSpa.setUnmountMaxTime(3000);
// After three seconds, move the application to SKIP_BECAUSE_BROKEN status.
singleSpa.setUnmountMaxTime(3000, true);
// don't do a console warning for slow lifecycles until 10 seconds have elapsed
singleSpa.setUnmountMaxTime(3000, true, 10000);
Arguments
同上
setUnloadMaxTime
設定 unload 的超時時間
// After three seconds, show a console warning while continuing to wait.
singleSpa.setUnloadMaxTime(3000);
// After three seconds, move the application to SKIP_BECAUSE_BROKEN status.
singleSpa.setUnloadMaxTime(3000, true);
// don't do a console warning for slow lifecycles until 10 seconds have elapsed
singleSpa.setUnloadMaxTime(3000, true, 10000);
Arguments
同上
Event
single-spa 將事件觸發到視窗,作為您的程式碼掛接到URL過渡的一種方式
PopStateEvent
當 single-spa 想要所有啟用的應用重新渲染時,通過該事件觸發。當一個應用程式呼叫history.pushState,history.replaceState或triggerAppChange時,就會發生這種情況。
window.addEventListener('popstate', evt => {
if (evt.singleSpa) {
console.log('This event was fired by single-spa to forcibly trigger a re-render')
console.log(evt.singleSpaTrigger); // pushState | replaceState
} else {
console.log('This event was fired by native browser behavior')
}
});
Canceling navigation
取消導航是指更改URL,然後立即將其更改回之前的狀態。這個發生在 mounting 、unmounting 或者 loading 之前完成。可以與Vue路由器和Angular路由器的內建導航保護功能結合使用,這些功能可以取消導航事件。
// 監聽 single-spa:before-routing-event 事件
window.addEventListener('single-spa:before-routing-event', ({detail: {oldUrl, newUrl, cancelNavigation}}) => {
if (new URL(oldUrl).pathname === '/route1' && new URL(newUrl).pathname === '/route2') {
cancelNavigation();
}
})
Custom Events
每當重新路由時,single-spa都會觸發一系列自定義事件。每當瀏覽器URL發生任何更改或呼叫triggerAppChange時,都會發生重新路由
window.addEventListener('single-spa:before-routing-event', evt => {
const { originalEvent, newAppStatuses, appsByNewStatus, totalAppChanges, oldUrl, newUrl, navigationIsCanceled, cancelNavigation } = evt.detail;
console.log('original event that triggered this single-spa event', originalEvent); // PopStateEvent | HashChangeEvent | undefined
console.log('the new status for all applications after the reroute finishes', newAppStatuses) // { app1: MOUNTED, app2: NOT_MOUNTED }
console.log('the applications that changed, grouped by their status', appsByNewStatus) // { MOUNTED: ['app1'], NOT_MOUNTED: ['app2'] }
console.log('number of applications that changed status so far during this reroute', totalAppChanges); // 2
console.log('the URL before the navigationEvent', oldUrl); // http://localhost:8080/old-route
console.log('the URL after the navigationEvent', newUrl); // http://localhost:8080/new-route
console.log('has the navigation been canceled', navigationIsCanceled); // false
// The cancelNavigation function is only defined in the before-routing-event
evt.detail.cancelNavigation();
})
before-app-change event
當至少一個應用程式更改狀態,在重新路由之前會觸發 single-spa:before-app-change事件。
window.addEventListener('single-spa:before-app-change', (evt) => {
console.log('single-spa is about to mount/unmount applications!');
console.log(evt.detail.originalEvent) // PopStateEvent
console.log(evt.detail.newAppStatuses) // { app1: MOUNTED }
console.log(evt.detail.appsByNewStatus) // { MOUNTED: ['app1'], NOT_MOUNTED: [] }
console.log(evt.detail.totalAppChanges) // 1
});
before-no-app-change
當零個應用程式更改狀態,在重新路由之前會觸發 single-spa:before-no-app-change事件。
window.addEventListener('single-spa:before-no-app-change', (evt) => {
console.log('single-spa is about to do a no-op reroute');
console.log(evt.detail.originalEvent) // PopStateEvent
console.log(evt.detail.newAppStatuses) // { }
console.log(evt.detail.appsByNewStatus) // { MOUNTED: [], NOT_MOUNTED: [] }
console.log(evt.detail.totalAppChanges) // 0
});
before-routing-event
在每個路由事件發生之前(即在每個hashchange,popstate或triggerAppChange之後)都會觸發 single-spa:before-routing-event 事件,即使不需要更改已註冊的應用程式也是如此。
window.addEventListener('single-spa:before-routing-event', (evt) => {
console.log('single-spa is about to mount/unmount applications!');
console.log(evt.detail.originalEvent) // PopStateEvent
console.log(evt.detail.newAppStatuses) // { }
console.log(evt.detail.appsByNewStatus) // { MOUNTED: [], NOT_MOUNTED: [] }
console.log(evt.detail.totalAppChanges) // 0
});
before-mount-routing-event
在 routing-event 之前,在 before-routing-event 之後,保證在所有應用 unmounted 之後,所有新應用 mounted 之前觸發
window.addEventListener('single-spa:before-mount-routing-event', (evt) => {
console.log('single-spa is about to mount/unmount applications!');
console.log(evt.detail)
console.log(evt.detail.originalEvent) // PopStateEvent
console.log(evt.detail.newAppStatuses) // { app1: MOUNTED }
console.log(evt.detail.appsByNewStatus) // { MOUNTED: ['app1'], NOT_MOUNTED: [] }
console.log(evt.detail.totalAppChanges) // 1
});
before-first-mount
在任何一個應用第一次掛載之前觸發,因此只觸發一次,這在應用已經載入好但是還沒 mounting 之後。
window.addEventListener('single-spa:before-first-mount', () => {
console.log('single-spa is about to mount the very first application for the first time');
});
first-mount
在任何一個應用第一次掛載之前觸發,因此只觸發一次
window.addEventListener('single-spa:first-mount', () => {
console.log('single-spa just mounted the very first application');
});
app-change event
至少一個應用 loaded、bootstrap、mounted、unmounted 或者 unloaded 觸發,hashchange,popstate 或triggerAppChange不會導致觸發事件。
window.addEventListener('single-spa:app-change', (evt) => {
console.log('A routing event occurred where at least one application was mounted/unmounted');
console.log(evt.detail.originalEvent) // PopStateEvent
console.log(evt.detail.newAppStatuses) // { app1: MOUNTED, app2: NOT_MOUNTED }
console.log(evt.detail.appsByNewStatus) // { MOUNTED: ['app1'], NOT_MOUNTED: ['app2'] }
console.log(evt.detail.totalAppChanges) // 2
});
no-app-change event
當沒有應用 loaded、boostrapped 、mounted、unmounted 或者 unloaded 時觸發。每個路由事件只會觸發一個。
window.addEventListener('single-spa:no-app-change', (evt) => {
console.log('A routing event occurred where zero applications were mounted/unmounted');
console.log(evt.detail.originalEvent) // PopStateEvent
console.log(evt.detail.newAppStatuses) // { }
console.log(evt.detail.appsByNewStatus) // { MOUNTED: [], NOT_MOUNTED: [] }
console.log(evt.detail.totalAppChanges) // 0
});
routing-event
每次發生路由事件時(在每個hashchange,popstate或triggerAppChange之後),都會觸發 single-spa:routing-event事件,即使無需更改已註冊的應用程式;之後 single-spa 會驗證所有應用正確 loaded、bootstrapped、mounted、unmounted
window.addEventListener('single-spa:routing-event', (evt) => {
console.log('single-spa finished mounting/unmounting applications!');
console.log(evt.detail.originalEvent) // PopStateEvent
console.log(evt.detail.newAppStatuses) // { app1: MOUNTED, app2: NOT_MOUNTED }
console.log(evt.detail.appsByNewStatus) // { MOUNTED: ['app1'], NOT_MOUNTED: ['app2'] }
console.log(evt.detail.totalAppChanges) // 2
});
相關文章
- 微前端 Micro-Frontends - Single-SPA前端
- 初步認識微前端(single-spa 和 qiankun)前端
- 微前端框架 之 single-spa 從入門到精通前端框架
- 微前端框架single-spa子應用載入解析前端框架
- 使用React,Vue和Single-spa構建微前端Micro FrontendsReactVue前端
- Angular 微前端實踐 之 Single-SPA 手把手教程(上)Angular前端
- 「實踐篇」解決微前端 single-spa 專案中 Vue 和 React 路由跳轉問題前端VueReact路由
- 微前端實踐前端
- 微前端如何落地?前端
- 微前端microApp前端APP
- 微前端架構前端架構
- 微前端方案前端
- Building a RESTful API in a Rails ApplicationUIRESTAPIAIAPP
- 也聊聊微前端(上)前端
- 淺析微前端沙箱前端
- 微前端開發(Vue)前端Vue
- 從0實現一個single-spa的前端微服務(下)前端微服務
- 從0實現一個single-spa的前端微服務(中)前端微服務
- 前端單頁應用微服務化解決方案2 - Single-SPA前端微服務
- c# 呼叫微吼直播APIC#API
- 微前端 Micro-Frontends - 概念前端
- qiankun微前端實踐前端
- 微前端說明以及使用前端
- 微前端專案部署方案前端
- 淺談qiankun微前端前端
- 熱點微前端Microfrontend的討論:谷歌AdWords是真實的微前端前端谷歌
- 效率前端微應用推進之微前端研發提效|得物技術前端
- 前端微模組更值得被推崇!前端
- 微前端(singleSpa + React )試玩前端React
- 前端微架構實踐(Vue)前端架構Vue
- 瞭解什麼是微前端前端
- 使用開源微前端框架 Luigi 建立一個基於微前端架構的工程前端框架UI架構
- 微前端概述(Micro Frontends) 以及相比單體應用,微前端能帶來什麼好處前端
- 聊聊微前端的原理和實踐前端
- 微前端的現狀和趨勢前端
- 微前端框架chunchao(春潮)開源啦前端框架
- 實施微前端的六種方式前端
- 「譯」用 Blazor WebAssembly 實現微前端BlazorWeb前端