loadMicroApp
loadMicroApp is qiankun's recommended loading primitive. It mounts a micro-app into a DOM element and returns a handle for managing that instance. The same model works for page regions, tabs, dialogs, and apps controlled by host state.
Use registerMicroApps with start only when an app must activate automatically from the URL.
This is the same primitive the framework wrappers <MicroApp> for React and <MicroApp> for Vue build on.
Signature
function loadMicroApp<T extends ObjectType>(
app: LoadableApp<T>,
configuration?: AppConfiguration,
lifeCycles?: LifeCycles<T>,
): MicroApp;loadMicroApp returns a MicroApp handle (a single-spa Parcel) that you use to observe status and to unmount the app. It does not wait — the load and mount run asynchronously; await the promises on the returned handle to observe completion.
Parameters
app: LoadableApp<T>
Describes which micro-app to load and where to mount it.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Micro-app name. Multiple instances may reuse it; concurrently mounted instances still need separate containers. |
entry | string | yes | URL of the micro-app's HTML entry. Always a string — the 2.x object form ({ scripts, styles }) does not exist in v3. |
container | HTMLElement | yes | The DOM element to render into. Must be an actual element, not a CSS-selector string. |
props | T | no | Business data passed to mount, unmount, and optional update, excluding bootstrap. |
type ObjectType = Record<string, unknown>;
type LoadableApp<T extends ObjectType> = {
name: string;
entry: string;
container: HTMLElement;
props?: T;
};container must be an element
In qiankun v3, container is an HTMLElement, not a string | HTMLElement. Resolve the element yourself (document.getElementById(...), a framework ref, etc.) before passing it. A selector string is a type error and will not work at runtime.
configuration?: AppConfiguration
Per-app options. All fields are optional; the defaults below are resolved internally.
| Option | Type | Default | Description |
|---|---|---|---|
sandbox | boolean | SandboxConfiguration | true | Enables the Proxy-membrane JS sandbox and the ESM sandbox. Set false only for legacy apps that must run against the real global; pass an object to keep isolation on and configure it. |
fetch | typeof window.fetch | window.fetch | Custom fetch for the entry and loader-managed scripts, modules, and styles. |
streamTransformer | () => TransformStream<string, string> | — | Optional transform piped into the HTML stream. |
nodeTransformer | NodeTransformer | internal default | Rewrites each script/link/style node before it hits live DOM. Override only for advanced cases. |
type AppConfiguration = Partial<Pick<LoaderOpts, 'fetch' | 'streamTransformer' | 'nodeTransformer'>> & {
sandbox?: boolean | SandboxConfiguration;
};sandbox is the single umbrella for isolation. Its object form carries styleIsolation, globals, incubatorContext, plugins, and the Compartment module hooks:
loadMicroApp(app, {
sandbox: {
styleIsolation: true,
globals: { TENANT_ID: 'acme' },
},
});See AppConfiguration for the full reference.
lifeCycles?: LifeCycles<T>
Optional lifecycle hooks that run around this app's load, mount, and unmount. Each hook is a single function or an array of functions, and each receives (app, global) where global is the sandboxed window view.
type LifeCycleFn<T extends ObjectType> = (app: LoadableApp<T>, global: WindowProxy) => Promise<void>;
type LifeCycles<T extends ObjectType> = {
beforeLoad?: LifeCycleFn<T> | Array<LifeCycleFn<T>>;
beforeMount?: LifeCycleFn<T> | Array<LifeCycleFn<T>>;
afterMount?: LifeCycleFn<T> | Array<LifeCycleFn<T>>;
beforeUnmount?: LifeCycleFn<T> | Array<LifeCycleFn<T>>;
afterUnmount?: LifeCycleFn<T> | Array<LifeCycleFn<T>>;
};See Lifecycle hooks for details.
Return value
loadMicroApp returns a MicroApp handle compatible with the single-spa Parcel interface:
type MicroApp = Parcel;
type Parcel = {
mount(): Promise<null>;
unmount(): Promise<null>;
update?(customProps: object): Promise<any>;
getStatus():
| 'NOT_LOADED'
| 'LOADING_SOURCE_CODE'
| 'NOT_BOOTSTRAPPED'
| 'BOOTSTRAPPING'
| 'NOT_MOUNTED'
| 'MOUNTING'
| 'MOUNTED'
| 'UPDATING'
| 'UNMOUNTING'
| 'UNLOADING'
| 'SKIP_BECAUSE_BROKEN'
| 'LOAD_ERROR';
loadPromise: Promise<null>;
bootstrapPromise: Promise<null>;
mountPromise: Promise<null>;
unmountPromise: Promise<null>;
};| Member | Description |
|---|---|
mount() | Mounts the parcel. loadMicroApp already mounts on load, so you rarely call this directly. |
unmount() | Unmounts the app, deactivates the sandbox, cleans up tracked side effects, and clears the container DOM. Always call this when you are done. |
update?(props) | Present only if the micro-app exports an update lifecycle. Pushes new props to the running app. |
getStatus() | Returns the current lifecycle status from the union above. |
loadPromise | Resolves when the source has finished loading. |
bootstrapPromise | Resolves when bootstrap has finished. |
mountPromise | Resolves when mount has finished. Await this to know the app is on screen. |
unmountPromise | Resolves when unmount has finished. |
The four promises retain single-spa Parcel's one-shot semantics: they describe the first load, bootstrap, mount, and unmount and are not replaced on remount. For subsequent mount() and unmount() calls, await the promise returned by the method; already-settled mountPromise and unmountPromise do not track later cycles.
Handle rejections
The promises reject if loading or mounting fails. Attach a .catch (or wrap in try/await) so failures do not surface as unhandled rejections.
Behavior
Observable behavior for callers:
- Loading and mounting start immediately. You do not call
start()first; awaitmountPromisewhen you need to know the app is visible. - One container hosts one app at a time. When apps are loaded into the same container in succession, the next instance waits for the previous one to unmount.
- An app name prefers existing instances. Calls with the same
nameandentryreuse an idle instance without executing the entry orbootstrapagain. If none is idle, a suitable unmounting instance can be reused after its teardown finishes. When no instance can be reused, qiankun loads a new copy. Anameshould always refer to the same app, and per-mount state belongs inmount(). - Idle instances have capacity and time limits. qiankun retains at most 2 idle instances per
nameandentry, and 8 globally. Exceeding either limit evicts the least recently used idle instance; 5 minutes of continuous idle time also triggers reclamation. Loading, mounting, queued, and unmounting instances are excluded. Reclamation does not clear the separate resource request cache. - Old handles can mount again after reclamation. After
unmount(), call the same handle'smount()to reuse a cached sandbox. If its cache entry was reclaimed and no other instance can be reused, qiankun reloads and executes the entry,bootstrap, andmount. Do not depend on module top-level code always running, or never running, on every mount. - The caller owns teardown. Call
unmount()when the app is no longer shown so qiankun can clear the container and release side effects it tracks.
See Run multiple micro-app instances for the complete guidance on reuse and remounting.
Example
Resolve a container element, mount the app, then unmount it when you no longer need it.
import { loadMicroApp } from 'qiankun';
const container = document.getElementById('micro-app-slot');
if (!container) throw new Error('container not found');
const microApp = loadMicroApp(
{
name: 'app1',
entry: 'http://localhost:7101',
container,
props: { userId: 42 },
},
{ sandbox: true },
);
// wait until it is on screen
await microApp.mountPromise;
console.log(microApp.getStatus()); // 'MOUNTED'
// later, tear it down
await microApp.unmount();For a legacy app that cannot run under isolation, disable the sandbox:
const microApp = loadMicroApp({ name: 'legacy-app', entry: 'http://localhost:7200', container }, { sandbox: false });React and Vue wrappers
If the host uses React or Vue, the corresponding <MicroApp> component can manage the container ref, prop updates, and unmount. These wrappers use the same loadMicroApp instance model.
Related
- registerMicroApps — route-driven activation instead of manual mounting.
- start — auto-invoked by
loadMicroApp, but call it explicitly for route-driven apps. - AppConfiguration — the full option reference.
- Lifecycle hooks — the
LifeCycleshooks. - Micro-app lifecycle and props — how props and lifecycles reach the sub-app.
- Run multiple micro-app instances — patterns for multiple instances on a page.
