Configuration
qiankun provides flexible configuration options to customize the behavior of micro-frontend applications. This document covers all available configuration options for different use cases.
📋 Configuration Types
AppConfiguration
Configuration for individual micro applications used with loadMicroApp.
type AppConfiguration = {
sandbox?: boolean | SandboxConfiguration;
fetch?: Function;
streamTransformer?: Function;
nodeTransformer?: Function;
};SandboxConfiguration
The umbrella configuration for the JS sandbox. Structurally it is a public projection of CompartmentOptions plus two qiankun host extensions (plugins and styleIsolation).
type SandboxConfiguration = Pick<
CompartmentOptions,
'globals' | 'incubatorContext' | 'modules' | 'resolveHook' | 'importHook' | 'loadHook'
> & {
plugins?: readonly IsolationPlugin[];
styleIsolation?: boolean;
};StartOpts
Configuration for starting the qiankun framework used with start().
interface StartOpts {
prefetch?: boolean | 'all' | string[] | ((apps: RegistrableApp[]) => { criticalAppNames: string[]; minorAppsName: string[] });
sandbox?: boolean | SandboxConfiguration;
singular?: boolean;
urlRerouteOnly?: boolean;
// ... other single-spa options
}⚙️ App Configuration Options
sandbox
Type: boolean | SandboxConfiguration
Default: true
Description: The single umbrella switch for the JS sandbox. false disables isolation entirely; true (the default) enables it with defaults; an object enables it and configures the underlying Compartment.
Basic Usage
// Enable sandbox (default)
loadMicroApp({
name: 'my-app',
entry: '//localhost:8080',
container: '#container',
}, {
sandbox: true
});
// Disable sandbox (not recommended)
loadMicroApp({
name: 'legacy-app',
entry: '//localhost:8080',
container: '#container',
}, {
sandbox: false
});
// Enable and configure sandbox
loadMicroApp({
name: 'configured-app',
entry: '//localhost:8080',
container: '#container',
}, {
sandbox: {
styleIsolation: true,
globals: { FEATURE_FLAG: true },
}
});Why Use Sandbox?
// With sandbox enabled, global variables are isolated
loadMicroApp({
name: 'app1',
entry: '//localhost:8001',
container: '#container1',
}, {
sandbox: true // app1 gets its own global scope
});
loadMicroApp({
name: 'app2',
entry: '//localhost:8002',
container: '#container2',
}, {
sandbox: true // app2 gets its own isolated global scope
});sandbox.incubatorContext
Type: WindowProxy
Default: window
Description: The host context that incubates the sandbox — the global the sandbox reads through for properties it has not shadowed. Named after the "incubator realm" of the ShadowRealm proposal; the Compartment spec has no equivalent because Compartments isolate by absence, while qiankun isolates by projection of a host context.
// Create a custom incubator context
const customGlobal = new Proxy(window, {
get(target, prop) {
// Custom logic for property access
if (prop === 'customAPI') {
return { version: '1.0' };
}
return target[prop];
}
});
loadMicroApp({
name: 'custom-app',
entry: '//localhost:8080',
container: '#container',
}, {
sandbox: {
incubatorContext: customGlobal
}
});sandbox.globals
Type: Record<string, unknown | PropertyDescriptor>
Default: {}
Description: Values and descriptors installed on this application's compartment global without modifying the host window. The name follows the globals endowments of the Compartment spec.
loadMicroApp(app, {
sandbox: {
globals: {
tenantId: 'acme',
featureClient: { value: createFeatureClient(), writable: false },
},
},
});Configured keys are available to both classic and ESM applications. See Extending sandbox isolation for descriptor rules.
sandbox.plugins
Type: IsolationPlugin[]
Default: []
Description: Application isolation plugins appended after qiankun's built-in plugins.
bootstrap plugins run before application scripts. mount plugins run on every mount, and their returned Free functions participate in unmount cleanup and remount recovery. See Extending sandbox isolation for the complete protocol and an external plugin example.
sandbox.styleIsolation
Type: boolean
Default: false
Description: Enable runtime CSS isolation: every micro-app style is scoped to the app container via CSS @scope.
loadMicroApp(app, {
sandbox: {
styleIsolation: true,
},
});Static entry styles are scoped by the loader transpiler, while dynamically injected styles ride on the sandbox's DOM interception — which is why CSS isolation lives inside the sandbox object and is only configurable while the JS sandbox is enabled. An isolated-CSS-without-sandbox combination would silently leak dynamic styles.
Module hooks (sandbox.modules / resolveHook / importHook / loadHook)
Type: module-related CompartmentOptions
Default: {}
Description: Advanced module resolution and loading hooks for this application's Compartment, set directly on the sandbox object.
Use modules, resolveHook, importHook, or its loadHook alias to provide redirects, private protocols, or precompiled module sources. These hooks affect sandboxed ESM loading only.
fetch
Type: Function
Default: window.fetch
Description: Custom fetch function for loading application resources.
Custom Headers
const customFetch = async (url, options) => {
return fetch(url, {
...options,
headers: {
...options?.headers,
'Authorization': `Bearer ${getToken()}`,
'X-Custom-Header': 'custom-value'
}
});
};
loadMicroApp({
name: 'authenticated-app',
entry: '//localhost:8080',
container: '#container',
}, {
fetch: customFetch
});Request Transformation
const transformFetch = async (url, options) => {
// Transform URLs
const transformedUrl = url.replace('//localhost', '//production-domain');
// Add custom logic
console.log(`Fetching: ${transformedUrl}`);
const response = await fetch(transformedUrl, options);
// Transform response
if (!response.ok) {
throw new Error(`Failed to fetch ${transformedUrl}: ${response.status}`);
}
return response;
};Caching Strategy
const cache = new Map();
const cachingFetch = async (url, options) => {
const cacheKey = `${url}${JSON.stringify(options)}`;
if (cache.has(cacheKey)) {
console.log(`Cache hit for ${url}`);
return cache.get(cacheKey);
}
const response = await fetch(url, options);
cache.set(cacheKey, response.clone());
return response;
};streamTransformer
Type: Function
Description: Transform streaming HTML content during loading.
const customStreamTransformer = (stream) => {
return stream.pipeThrough(new TransformStream({
transform(chunk, controller) {
// Transform HTML chunks
const transformedChunk = chunk
.replace(/old-api/g, 'new-api')
.replace(/deprecated-feature/g, 'updated-feature');
controller.enqueue(transformedChunk);
}
}));
};
loadMicroApp({
name: 'streaming-app',
entry: '//localhost:8080',
container: '#container',
}, {
streamTransformer: customStreamTransformer
});nodeTransformer
Type: Function
Description: Transform DOM nodes during application loading.
const customNodeTransformer = (node, options) => {
// Transform script tags
if (node.tagName === 'SCRIPT') {
// Add custom attributes
node.setAttribute('data-app', 'my-app');
// Modify script source
if (node.src) {
node.src = node.src.replace('localhost', 'production-domain');
}
}
// Transform style tags
if (node.tagName === 'STYLE') {
// Add CSS scope
node.textContent = `.app-scope { ${node.textContent} }`;
}
return node;
};
loadMicroApp({
name: 'transformed-app',
entry: '//localhost:8080',
container: '#container',
}, {
nodeTransformer: customNodeTransformer
});🚀 Start Configuration Options
prefetch
Type: boolean | 'all' | string[] | Function
Default: true
Description: Resource prefetching strategy for better performance.
Boolean Values
// Disable prefetch
start({ prefetch: false });
// Enable default prefetch
start({ prefetch: true });Prefetch All
// Prefetch all registered micro apps
start({ prefetch: 'all' });Selective Prefetch
// Prefetch specific apps
start({
prefetch: ['dashboard', 'user-profile', 'analytics']
});Dynamic Prefetch Strategy
start({
prefetch: (apps) => {
// Business logic to determine prefetch strategy
const currentTime = new Date().getHours();
const isBusinessHours = currentTime >= 9 && currentTime <= 17;
if (isBusinessHours) {
// Prefetch business-critical apps during business hours
return {
criticalAppNames: ['dashboard', 'crm', 'finance'],
minorAppsName: ['reporting', 'settings']
};
} else {
// Minimal prefetch during off-hours
return {
criticalAppNames: ['dashboard'],
minorAppsName: []
};
}
}
});User-based Prefetch
start({
prefetch: (apps) => {
const userRole = getCurrentUserRole();
switch (userRole) {
case 'admin':
return {
criticalAppNames: ['admin-panel', 'user-management', 'system-monitor'],
minorAppsName: ['reports', 'settings']
};
case 'user':
return {
criticalAppNames: ['dashboard', 'profile'],
minorAppsName: ['help', 'feedback']
};
default:
return {
criticalAppNames: ['dashboard'],
minorAppsName: []
};
}
}
});sandbox
Type: boolean | SandboxConfiguration
Default: true
Description: Framework-level sandbox configuration for all micro applications.
Basic Sandbox
// Enable sandbox for all apps
start({ sandbox: true });
// Disable sandbox for all apps (not recommended)
start({ sandbox: false });Advanced Sandbox Configuration
start({
sandbox: {
styleIsolation: true, // Scope every micro-app style to its container via CSS @scope
}
});Style Isolation
styleIsolation: Scopes all micro-app styles to the app container via CSS @scope
start({
sandbox: {
styleIsolation: true, // Good balance of isolation and compatibility
}
});singular
Type: boolean
Default: true
Description: Whether only one micro app can be mounted at a time.
// Only one app at a time (default)
start({ singular: true });
// Allow multiple apps simultaneously
start({
singular: false // Useful for dashboard-style applications
});Use Cases for Multiple Apps
// Dashboard with multiple widgets
start({
singular: false,
// Other configurations
});
// Register widget-style micro apps
registerMicroApps([
{ name: 'widget-weather', entry: '//localhost:8001', container: '#widget-1', activeRule: '/dashboard' },
{ name: 'widget-stocks', entry: '//localhost:8002', container: '#widget-2', activeRule: '/dashboard' },
{ name: 'widget-news', entry: '//localhost:8003', container: '#widget-3', activeRule: '/dashboard' },
]);urlRerouteOnly
Type: boolean
Default: true
Description: Whether to trigger routing only on URL changes.
// Only route on URL changes (default)
start({ urlRerouteOnly: true });
// Route on both URL and programmatic changes
start({
urlRerouteOnly: false // More responsive but potentially more performance overhead
});🔧 Environment-based Configuration
Development Configuration
const developmentConfig = {
prefetch: false, // Faster rebuilds
sandbox: {
styleIsolation: false, // Unscoped styles are easier to debug
},
singular: false, // More flexible development
urlRerouteOnly: false, // More responsive navigation
};
if (process.env.NODE_ENV === 'development') {
start(developmentConfig);
}Production Configuration
const productionConfig = {
prefetch: 'all', // Better user experience
sandbox: {
styleIsolation: true, // Scope styles to each app container
},
singular: true, // Stable performance
urlRerouteOnly: true, // Optimized routing
};
if (process.env.NODE_ENV === 'production') {
start(productionConfig);
}Mobile Configuration
const mobileConfig = {
prefetch: (apps) => ({
// Conservative prefetch on mobile
criticalAppNames: ['home'],
minorAppsName: []
}),
sandbox: {
// @scope-based style isolation stays lightweight on mobile
styleIsolation: true,
},
singular: true, // Better for mobile UX
};
const isMobile = window.innerWidth < 768;
if (isMobile) {
start(mobileConfig);
}🎯 Advanced Configuration Patterns
1. Feature Flag Integration
const getConfigWithFeatureFlags = async () => {
const featureFlags = await getFeatureFlags();
return {
prefetch: featureFlags.enablePrefetch ? 'all' : false,
sandbox: {
styleIsolation: featureFlags.styleIsolation,
},
singular: featureFlags.allowMultipleApps ? false : true,
};
};
getConfigWithFeatureFlags().then(config => start(config));2. Performance-based Configuration
const getPerformanceConfig = () => {
const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
const isSlowConnection = connection?.effectiveType === '2g' || connection?.effectiveType === 'slow-2g';
if (isSlowConnection) {
return {
prefetch: false, // No prefetch on slow connections
sandbox: true, // Default isolation, no extra work
singular: true,
};
}
return {
prefetch: 'all',
sandbox: {
styleIsolation: true,
},
singular: false,
};
};
start(getPerformanceConfig());3. User Role-based Configuration
const getRoleBasedConfig = (userRole) => {
const baseConfig = {
sandbox: true,
singular: true,
};
switch (userRole) {
case 'admin':
return {
...baseConfig,
prefetch: 'all', // Admins get all features
singular: false, // Can use multiple admin tools
};
case 'poweruser':
return {
...baseConfig,
prefetch: ['dashboard', 'analytics', 'reports'],
singular: false,
};
default:
return {
...baseConfig,
prefetch: ['dashboard'], // Basic users get minimal prefetch
singular: true,
};
}
};
const userRole = getCurrentUserRole();
start(getRoleBasedConfig(userRole));⚠️ Important Notes
1. Configuration Precedence
// App-level configuration overrides framework-level configuration
start({
sandbox: true, // Framework-level setting
});
loadMicroApp({
name: 'special-app',
entry: '//localhost:8080',
container: '#container',
}, {
sandbox: false // This overrides the framework-level setting for this app
});The merge is a shallow spread ({ ...frameworkConfiguration, ...appConfiguration }): a per-app sandbox object replaces the framework-level one entirely — there is no deep merge of individual sandbox fields.
2. Performance Considerations
// ❌ Bad: Heavy configuration that impacts performance
start({
prefetch: 'all', // Might slow down initial load
singular: false, // More memory usage
urlRerouteOnly: false, // More frequent route checks
});
// ✅ Good: Balanced configuration
start({
prefetch: ['critical-app'], // Only prefetch what's needed
sandbox: {
styleIsolation: true, // Lightweight @scope-based CSS isolation
},
singular: true, // Stable performance
urlRerouteOnly: true, // Optimized routing
});3. Debugging Configuration
const debugConfig = {
sandbox: {
styleIsolation: false, // Unscoped styles are easier to inspect
},
// Custom fetch for logging
fetch: async (url, options) => {
console.log(`[DEBUG] Fetching: ${url}`);
const response = await fetch(url, options);
console.log(`[DEBUG] Response: ${response.status}`);
return response;
},
// Custom node transformer for debugging
nodeTransformer: (node, options) => {
if (node.tagName === 'SCRIPT') {
console.log(`[DEBUG] Processing script: ${node.src || 'inline'}`);
}
return node;
}
};🔗 Related APIs
- start - Start qiankun with configuration
- loadMicroApp - Load app with configuration
- registerMicroApps - Register apps
