Applications API

single-spa exports named functions and variables rather than a single default export. This means importing must happen in one of two ways:

import { registerApplication, start } from 'single-spa';
// or
import * as singleSpa from 'single-spa';

registerApplication

singleSpa.registerApplication('appName', () => System.import('appName'), location => location.pathname.startsWith('appName'))

registerApplication is the most important api your single spa config will use. Use this function to register any application within single-spa.

Note that if an application is registered from within another application, that no hierarchy will be maintained between the applications.

It is described in detail inside of the /docs/configuration docs

arguments

appName: string
App name that single-spa will register and reference this application with, and will be labelled with in dev tools.
applicationOrLoadingFn: () => <Function | Promise>
Must be a loading function that either returns the resolved application or a promise.
activityFn: (location) => boolean
Must be a pure function. The function is called with
window.location
as the first argument !-- TODO: any only? --> and should return a truthy value whenever the application should be active.
customProps?: Object =
Will be passed to the application during each lifecycle method.

returns

undefined

start

singleSpa.start();

Must be called by your single spa config. Before start is called, applications will be loaded, but will never be bootstrapped, mounted or unmounted. The reason for start is to give you control over the performance of your single page application. For example, you may want to declare registered applications immediately (to start downloading the code for the active ones), but not actually mount the registered applications until an initial AJAX request (maybe to get information about the logged in user) has been completed. In that case, the best performance is achieved by calling registerApplication immediately, but calling start after the AJAX request is completed.

arguments

none

returns

undefined

triggerAppChange

singleSpa.triggerAppChange();

Returns a Promise that will resolve/reject when all apps have mounted/unmounted. This was built for testing single-spa and is likely not needed in a production application.

arguments

none

returns

Promise
Returns a Promise that will resolve/reject when all apps have mounted.

navigateToUrl

// Three ways of using navigateToUrl
singleSpa.navigateToUrl("/new-url");
singleSpa.navigateToUrl(document.querySelector('a'));
document.querySelector('a').addEventListener(singleSpa.navigateToUrl);
<!-- A fourth way to use navigateToUrl, this one inside of your HTML -->
<a href="/new-url" onclick="singleSpaNavigate()">My link</a>

Use this utility function to easily perform url navigation between registered applications without needing to deal with event.preventDefault(), pushState, triggerAppChange(), etc.

arguments

navigationObj: string | context | DOMEvent
navigationObj must be one of the following types:
  • a url string.
  • a context / thisArg that has an
    href
    property; useful for calling
    singleSpaNavigate.call(anchorElement)
    with a reference to the anchor element or other context.
  • a DOMEvent object for a click event on a DOMElement that has an
    href
    attribute; ideal for the
    <a onclick="singleSpaNavigate"></a>
    use case.

returns

undefined

getMountedApps

const mountedAppNames = singleSpa.getMountedApps();
console.log(mountedAppNames); // ['app1', 'app2', 'navbar']

arguments

none

returns

appNames: string[]
Each string is the name of a registered application that is currently
MOUNTED
.

getAppNames

const appNames = singleSpa.getAppNames();
console.log(appNames); // ['app1', 'app2', 'app3', 'navbar']

arguments

none

returns

appNames: string[]
Each string is the name of a registered application regardless of app status.

getAppStatus

const status = singleSpa.getAppStatus('app1');
console.log(status); // one of many statuses (see list below). e.g. MOUNTED

arguments

appName: string
Registered application name.

returns

appStatus: <string | null>
Will be one of the following string constants, or
null
if the app does not exist.
NOT_LOADED
app has been registered with single-spa but has not yet been loaded.
LOADING_SOURCE_CODE
's source code is being fetched.
NOT_BOOTSTRAPPED
app has been loaded but not bootstrapped.
BOOTSTRAPPING
the
bootstrap
lifecycle function has been called but has not finished.
NOT_MOUNTED
app has been loaded and bootstrapped but not yet mounted.
MOUNTING
app is being mounted but not finished.
MOUNTED
app is currently active and is mounted to the DOM.
UNMOUNTING
app is currently being unmounted but has not finished.
UNLOADING
app is currently being unloaded but has not finished.
SKIP_BECAUSE_BROKEN
app threw an error during load, bootstrap, mount, or unmount and has been siloed because it is misbehaving and has been skipped. Other apps will continue on normally.
LOAD_ERROR
The app's loading function returned a promise that rejected. This is often due to a network error attempting to download the javascript bundle for the application. Single-spa will retry loading the application after the user navigates away from the current route and then comes back to it.

Note about LOAD_ERROR status

Note that if you're using SystemJS to load your bundles, you need to add the following code to get SystemJS to re-attempt the network request when your loading function calls System.import() on an application in LOAD_ERROR status.

singleSpa.addErrorHandler(err => {
if (singleSpa.getAppStatus(err.appOrParcelName) === singleSpa.LOAD_ERROR) {
System.delete(System.resolve(err.appOrParcelName));
}
})

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});

The purpose of unloading a registered application is to set it back to to a NOT_LOADED status, which means that it will be re-bootstrapped the next time it needs to mount. The main use-case for this was to allow for the hot-reloading of entire registered applications, but unloadApplication can be useful whenever you want to re-bootstrap your application.

Single-spa performs the following steps when unloadApplication is called.

  1. Call the unload lifecyle on the registered application that is being unloaded.
  2. Set the app status to NOT_LOADED
  3. Trigger a reroute, during which single-spa will potentially mount the application that was just unloaded.

Because a registered application might be mounted when unloadApplication is called, you can specify whether you want to immediately unload or if you want to wait until the application is no longer mounted. This is done with the waitForUnmount option.

arguments

appName: string
Registered application name.
options?: {waitForUnmount: boolean = false}
The options must be an object that has a
waitForUnmount
property. When `waitForUnmount` is `false`, single-spa immediately unloads the specified registered application even if the app is currently mounted. If it is
true
, single-spa will unload the registered application as soon as it is safe to do so (when the app status is not
MOUNTED
).

returns

Promise
This promise will be resolved when the registered application has been successfully removed.

checkActivityFunctions

const appsThatShouldBeActive = singleSpa.checkActivityFunctions();
console.log(appsThatShouldBeActive); // ['app1']
const appsForACertainRoute = singleSpa.checkActivityFunctions({pathname: '/app2'});
console.log(appsForACertainRoute); // ['app2']

Will call every app's activity function with the mockWindowLocation and give you list of which applications should be mounted with that location.

arguments

mockWindowLocation: string
A string representing a window.location that will be used when calling every application's activity function to test if they return true.

returns

appNames: string[]
Each string is the name of a registered application that matches the provided
mockWindowLocation
.

addErrorHandler

singleSpa.addErrorHandler(err => {
console.log(err);
console.log(err.appOrParcelName);
console.log(singleSpa.getAppStatus(err.appOrParcelName));
});

Adds a handler that will be called every time an application throws an error during a lifecycle function or activity function. When there are no error handlers, single-spa throws the error to the window.

errorHandler: Function(error: Error)
Must be a function. Will be called with an Error object that additionally has a
message
and
appOrParcelName
property.

returns

undefined

removeErrorHandler

singleSpa.addErrorHandler(handleErr)
singleSpa.removeErrorHandler(handleErr)
function handleErr(err) {
console.log(err)
}

Removes the given error handler function.

arguments

errorHandler: Function
Reference to the error handling function.

returns

boolean
true
if the error handler was removed, and
false
if it was not.

mountRootParcel

const parcel = singleSpa.mountRootParcel(parcelConfig, {prop1: 'value1', domElement: document.getElementById('a-div')});
parcel.mountPromise.then(() => {
console.log('finished mounting the parcel!')
})

Will create and mount a single-spa parcel.

Note: parcels do not automatically unmount. Unmounting will need to be triggered manually.

arguments

parcelConfig: ???
[parcelConfig](/docs/parcels-api#parcel-configuration)
parcelProps: ???
[parcelProps](/docs/parcels-api#parcel-props)

returns

Parcel object
See Parcels API for more detail.

ensureJQuerySupport

singleSpa.ensureJQuerySupport(jQuery);

jQuery uses event delegation so single-spa must monkey-patch each version of jQuery on the page. single-spa will attempt to do this automatically by looking for window.jQuery or window.$. Use this explicit method if multiple versions are included on your page or if jQuery is bound to a different global variable.

arguments

jQuery?: JQueryFn = window.jQuery
A reference to the global variable that jQuery has been bound to.

returns

undefined

setBootstrapMaxTime

// 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);

Sets the global configuration for bootstrap timeouts.

arguments

millis: number
Number of milliseconds to wait for bootstrap to complete before timing out.
dieOnTimeout: boolean = false

If false, registered applications that are slowing things down will cause nothing more than some warnings in the console up until

millis
is reached.

If true, registered applications that are slowing things down will be siloed into a SKIP_BECAUSE_BROKEN status where they will never again be given the chance to break everything.

Each registered application can override this behavior for itself.

returns

undefined

setMountMaxTime

// 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);

Sets the global configuration for mount timeouts.

arguments

millis: number
Number of milliseconds to wait for mount to complete before timing out.
dieOnTimeout: boolean = false

If false, registered applications that are slowing things down will cause nothing more than some warnings in the console up until

millis
is reached.

If true, registered applications that are slowing things down will be siloed into a SKIP_BECAUSE_BROKEN status where they will never again be given the chance to break everything.

Each registered application can override this behavior for itself.

returns

undefined

setUnmountMaxTime

// 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);

Sets the global configuration for unmount timeouts.

arguments

millis: number
Number of milliseconds to wait for unmount to complete before timing out.
dieOnTimeout: boolean = false

If false, registered applications that are slowing things down will cause nothing more than some warnings in the console up until

millis
is reached.

If true, registered applications that are slowing things down will be siloed into a SKIP_BECAUSE_BROKEN status where they will never again be given the chance to break everything.

Each registered application can override this behavior for itself.

returns

undefined


Events

All of the following are custom events fired by single-spa on the window. The event detail property contains the native DOM event that triggered the reroute, such as a PopStateEvent or HashChangeEvent. These events can be handled by using addEventListener, like so:

window.addEventListener('single-spa:before-routing-event', evt => {
const originalEvent = evt.detail;
console.log('single-spa event', originalEvent);
})

before routing event

singleSpa.addEventListener('single-spa:before-routing-event', () => {
console.log('single-spa is about to mount/unmount applications!');
});

A single-spa:before-routing-event event is fired before every routing event occurs, which is after each hashchange, popstate, or triggerAppChange, even if no changes to registered applications were necessary.

routing event

singleSpa.addEventListener('single-spa:routing-event', () => {
console.log('single-spa finished mounting/unmounting applications!');
});

A single-spa:routing-event event is fired every time that a routing event has occurred, which is after each hashchange, popstate, or triggerAppChange, even if no changes to registered applications were necessary; and after single-spa verified that all apps were correctly loaded, bootstrapped, mounted, and unmounted.

app-change event

singleSpa.addEventListener('single-spa:app-change', () => {
console.log('A routing event occurred where at least one application was mounted/unmounted');
});

A single-spa:app-change event is fired every time that one or more apps were loaded, bootstrapped, mounted, unmounted, or unloaded. It is similar to single-spa:routing-event except that it will not fire unless one or more apps were actually loaded, bootstrapped, mounted, or unmounted. A hashchange, popstate, or triggerAppChange that does not result in one of those changes will not cause the event to be fired.

no-app-change event

singleSpa.addEventListener('single-spa:before-routing-event', () => {
console.log('A routing event occurred where zero applications were mounted/unmounted');
});

When no applications were loaded, bootstrapped, mounted, unmounted, or unloaded, single-spa fires a single-spa:no-app-change event. This is the inverse of the single-spa:app-change event. Only one will be fired for each routing event.

before-first-mount

singleSpa.addEventListener('single-spa:before-first-mount', () => {
console.log('single-spa is about to mount the very first application for the first time');
});

Before the first of any single-spa applications is mounted, single-spa fires a single-spa:before-first-mount event; therefore it will only be fired once ever. More specifically, it fires after the application is already loaded but before mounting.

Suggested use case: remove a loader bar that the user is seeing right before the first app will be mounted.

first-mount

singleSpa.addEventListener('single-spa:first-mount', () => {
console.log('single-spa just mounted the very first application');
});

After the first of any single-spa applications is mounted, single-spa fires a single-spa:first-mount event; therefore it will only be fired once ever.

Suggested use case: log the time it took before the user sees any of the apps mounted.