CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-single-spa

The router for easy microfrontends that enables multiple frameworks to coexist on the same page.

Pending
Overview
Eval results
Files

configuration-timeouts.mddocs/

Configuration & Timeouts

Configuration utilities for setting application lifecycle timeouts, framework startup options, and integration settings.

Capabilities

Start Single-SPA

Initializes single-spa and begins managing applications. This function must be called to activate the microfrontend system.

/**
 * Start single-spa and begin managing applications
 * @param opts - Optional configuration options
 */
function start(opts?: StartOpts): void;

interface StartOpts {
  urlRerouteOnly?: boolean;
}

Usage Examples:

import { start } from "single-spa";

// Basic start
start();

// Start with URL-only rerouting (performance optimization)
start({ urlRerouteOnly: true });

// Typical application initialization
import { registerApplication, start } from "single-spa";

// Register all applications first
registerApplication({
  name: "navbar",
  app: () => import("./navbar/navbar.app.js"),
  activeWhen: "/"
});

registerApplication({
  name: "main-content",
  app: () => import("./main/main.app.js"),
  activeWhen: "/app"
});

// Then start single-spa
start();

// Conditional start based on environment
if (window.singleSpaReady) {
  start();
} else {
  window.addEventListener("single-spa-ready", () => start());
}

Bootstrap Timeout Configuration

Sets the maximum time allowed for application bootstrapping. Applications that exceed this timeout will be marked as broken.

/**
 * Set maximum time for application bootstrap lifecycle
 * @param time - Timeout in milliseconds
 * @param dieOnTimeout - Whether to throw error on timeout (default: false)
 * @param warningMillis - Warning threshold in milliseconds (default: 1000)
 */
function setBootstrapMaxTime(
  time: number,
  dieOnTimeout?: boolean,
  warningMillis?: number
): void;

Usage Examples:

import { setBootstrapMaxTime } from "single-spa";

// Set 10 second bootstrap timeout
setBootstrapMaxTime(10000);

// Set timeout with error throwing enabled
setBootstrapMaxTime(5000, true);

// Set timeout with custom warning threshold
setBootstrapMaxTime(8000, false, 3000); // Warn after 3s, timeout after 8s

// Environment-based configuration
const isProduction = process.env.NODE_ENV === "production";
setBootstrapMaxTime(
  isProduction ? 5000 : 30000, // Shorter timeout in production
  isProduction, // Die on timeout in production
  isProduction ? 2000 : 5000 // Earlier warning in production
);

Mount Timeout Configuration

Sets the maximum time allowed for application mounting.

/**
 * Set maximum time for application mount lifecycle
 * @param time - Timeout in milliseconds
 * @param dieOnTimeout - Whether to throw error on timeout (default: false)
 * @param warningMillis - Warning threshold in milliseconds (default: 1000)
 */
function setMountMaxTime(
  time: number,
  dieOnTimeout?: boolean,
  warningMillis?: number
): void;

Usage Examples:

import { setMountMaxTime } from "single-spa";

// Standard mount timeout
setMountMaxTime(5000);

// Quick mount timeout for simple applications
setMountMaxTime(2000, true, 1000);

// Longer timeout for heavy applications
setMountMaxTime(15000, false, 5000);

// Dynamic timeout based on application complexity
function configureTimeouts() {
  const heavyApps = ["dashboard", "data-visualization"];
  const currentApp = getCurrentAppName();
  
  if (heavyApps.includes(currentApp)) {
    setMountMaxTime(10000, false, 3000);
  } else {
    setMountMaxTime(3000, true, 1000);
  }
}

Unmount Timeout Configuration

Sets the maximum time allowed for application unmounting.

/**
 * Set maximum time for application unmount lifecycle
 * @param time - Timeout in milliseconds
 * @param dieOnTimeout - Whether to throw error on timeout (default: false)
 * @param warningMillis - Warning threshold in milliseconds (default: 1000)
 */
function setUnmountMaxTime(
  time: number,
  dieOnTimeout?: boolean,
  warningMillis?: number
): void;

Usage Examples:

import { setUnmountMaxTime } from "single-spa";

// Quick unmount timeout
setUnmountMaxTime(3000);

// Strict unmount timeout
setUnmountMaxTime(2000, true);

// Graceful unmount with longer timeout
setUnmountMaxTime(8000, false, 2000);

Unload Timeout Configuration

Sets the maximum time allowed for application unloading.

/**
 * Set maximum time for application unload lifecycle
 * @param time - Timeout in milliseconds
 * @param dieOnTimeout - Whether to throw error on timeout (default: false)
 * @param warningMillis - Warning threshold in milliseconds (default: 1000)
 */
function setUnloadMaxTime(
  time: number,
  dieOnTimeout?: boolean,
  warningMillis?: number
): void;

Usage Examples:

import { setUnloadMaxTime } from "single-spa";

// Standard unload timeout
setUnloadMaxTime(5000);

// Force unload quickly
setUnloadMaxTime(3000, true);

jQuery Support

Ensures jQuery plays nicely with single-spa's routing system by preventing jQuery from interfering with navigation.

/**
 * Ensure jQuery doesn't interfere with single-spa routing
 * @param jQuery - Optional jQuery instance (auto-detected if not provided)
 */
function ensureJQuerySupport(jQuery?: any): void;

Usage Examples:

import { ensureJQuerySupport } from "single-spa";

// Auto-detect jQuery
ensureJQuerySupport();

// Provide specific jQuery instance
import $ from "jquery";
ensureJQuerySupport($);

// Conditional jQuery support
if (window.jQuery) {
  ensureJQuerySupport(window.jQuery);
}

Configuration Patterns

Environment-Based Configuration

import { 
  start, 
  setBootstrapMaxTime, 
  setMountMaxTime, 
  setUnmountMaxTime,
  addErrorHandler 
} from "single-spa";

class SingleSpaConfig {
  static configure() {
    const env = process.env.NODE_ENV;
    const isDev = env === "development";
    const isProd = env === "production";
    
    // Configure timeouts based on environment
    if (isDev) {
      // Generous timeouts for development
      setBootstrapMaxTime(30000, false, 10000);
      setMountMaxTime(15000, false, 5000);
      setUnmountMaxTime(10000, false, 3000);
    } else if (isProd) {
      // Strict timeouts for production
      setBootstrapMaxTime(5000, true, 2000);
      setMountMaxTime(3000, true, 1000);
      setUnmountMaxTime(2000, true, 500);
    }
    
    // Configure error handling
    if (isDev) {
      addErrorHandler((error) => {
        console.error("Development error:", error);
      });
    }
    
    // Start with appropriate options
    start({ 
      urlRerouteOnly: isProd // Performance optimization for production
    });
  }
}

// Initialize configuration
SingleSpaConfig.configure();

Progressive Configuration

import { 
  start, 
  setBootstrapMaxTime, 
  setMountMaxTime,
  registerApplication 
} from "single-spa";

// Configure timeouts progressively as applications are registered
const appConfigs = [
  {
    name: "shell",
    timeouts: { bootstrap: 3000, mount: 2000, unmount: 1000 }
  },
  {
    name: "heavy-dashboard",
    timeouts: { bootstrap: 10000, mount: 8000, unmount: 5000 }
  },
  {
    name: "simple-widget",
    timeouts: { bootstrap: 2000, mount: 1000, unmount: 500 }
  }
];

async function configureAndRegisterApps() {
  for (const config of appConfigs) {
    // Set timeouts for this specific app registration
    setBootstrapMaxTime(config.timeouts.bootstrap);
    setMountMaxTime(config.timeouts.mount);
    setUnmountMaxTime(config.timeouts.unmount);
    
    // Register the application
    registerApplication({
      name: config.name,
      app: () => import(`./apps/${config.name}/${config.name}.app.js`),
      activeWhen: `/${config.name}`
    });
  }
  
  // Start single-spa after all apps are registered
  start();
}

Performance Monitoring Configuration

import { 
  start, 
  setBootstrapMaxTime, 
  setMountMaxTime, 
  setUnmountMaxTime,
  addErrorHandler 
} from "single-spa";

class PerformanceMonitor {
  constructor() {
    this.metrics = new Map();
    this.setupTimeouts();
    this.setupErrorHandling();
  }
  
  setupTimeouts() {
    // Set timeouts with performance tracking
    const bootstrapTimeout = 5000;
    const mountTimeout = 3000;
    const unmountTimeout = 2000;
    
    setBootstrapMaxTime(bootstrapTimeout, false, bootstrapTimeout * 0.5);
    setMountMaxTime(mountTimeout, false, mountTimeout * 0.5);
    setUnmountMaxTime(unmountTimeout, false, unmountTimeout * 0.5);
  }
  
  setupErrorHandling() {
    addErrorHandler((error) => {
      if (error.message.includes("timeout")) {
        this.recordTimeout(error.appOrParcelName, error.message);
      }
    });
  }
  
  recordTimeout(appName, message) {
    const metric = this.metrics.get(appName) || { timeouts: 0, lastTimeout: null };
    metric.timeouts++;
    metric.lastTimeout = new Date();
    this.metrics.set(appName, metric);
    
    console.warn(`Performance issue: ${appName} timed out (${metric.timeouts} times)`);
    
    // Adjust timeouts dynamically
    if (metric.timeouts > 3) {
      console.log(`Increasing timeouts for ${appName} due to repeated issues`);
      this.increaseTimeouts(appName);
    }
  }
  
  increaseTimeouts(appName) {
    // Increase timeouts for problematic applications
    setBootstrapMaxTime(10000);
    setMountMaxTime(8000);
    setUnmountMaxTime(5000);
  }
  
  getPerformanceReport() {
    const report = {};
    this.metrics.forEach((metric, appName) => {
      report[appName] = {
        timeoutCount: metric.timeouts,
        lastTimeout: metric.lastTimeout,
        needsAttention: metric.timeouts > 2
      };
    });
    return report;
  }
}

// Initialize performance monitoring
const performanceMonitor = new PerformanceMonitor();

// Start single-spa
start();

Feature Flag Configuration

import { start, ensureJQuerySupport } from "single-spa";

class FeatureFlagConfig {
  static async configure() {
    // Load feature flags
    const flags = await this.loadFeatureFlags();
    
    // Configure based on flags
    if (flags.jquerySupport) {
      ensureJQuerySupport();
    }
    
    if (flags.urlRerouteOnly) {
      start({ urlRerouteOnly: true });
    } else {
      start();
    }
    
    if (flags.strictTimeouts) {
      this.configureStrictTimeouts();
    } else {
      this.configureRelaxedTimeouts();
    }
  }
  
  static async loadFeatureFlags() {
    try {
      const response = await fetch("/api/feature-flags");
      return await response.json();
    } catch (error) {
      console.warn("Failed to load feature flags, using defaults");
      return {
        jquerySupport: false,
        urlRerouteOnly: false,
        strictTimeouts: false
      };
    }
  }
  
  static configureStrictTimeouts() {
    setBootstrapMaxTime(3000, true, 1000);
    setMountMaxTime(2000, true, 500);
    setUnmountMaxTime(1000, true, 300);
  }
  
  static configureRelaxedTimeouts() {
    setBootstrapMaxTime(10000, false, 5000);
    setMountMaxTime(8000, false, 3000);
    setUnmountMaxTime(5000, false, 2000);
  }
}

// Initialize with feature flags
FeatureFlagConfig.configure();

Best Practices

Timeout Configuration Guidelines

// Recommended timeout configurations by application type

// Lightweight applications (simple widgets, headers, footers)
setBootstrapMaxTime(2000, true, 1000);
setMountMaxTime(1000, true, 500);
setUnmountMaxTime(500, true, 200);

// Standard applications (forms, content pages)
setBootstrapMaxTime(5000, false, 2000);
setMountMaxTime(3000, false, 1000);
setUnmountMaxTime(2000, false, 500);

// Heavy applications (dashboards, data visualization, complex SPAs)
setBootstrapMaxTime(10000, false, 5000);
setMountMaxTime(8000, false, 3000);
setUnmountMaxTime(5000, false, 2000);

// Legacy applications (older frameworks, complex dependencies)
setBootstrapMaxTime(15000, false, 8000);
setMountMaxTime(12000, false, 5000);
setUnmountMaxTime(8000, false, 3000);

Install with Tessl CLI

npx tessl i tessl/npm-single-spa

docs

application-management.md

application-status-lifecycle.md

configuration-timeouts.md

error-handling.md

index.md

navigation-routing.md

parcels-system.md

tile.json