or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

bundle-usage.mddynamic-loading.mdes5-adapter.mdevent-system.mdindex.md
tile.json

dynamic-loading.mddocs/

Dynamic Polyfill Loading

The webcomponents-loader.js provides intelligent feature detection and dynamic loading of only the necessary polyfill bundles, optimizing performance and reducing payload size.

Capabilities

Loader Script

Main entry point that detects browser capabilities and loads appropriate polyfill bundles.

/**
 * Include webcomponents-loader.js as a script tag
 * The loader automatically detects which polyfills are needed and loads them
 */
// <script src="webcomponents-loader.js"></script>

// After loading, global WebComponents object becomes available
interface WebComponents {
  /** Boolean indicating if polyfills are loaded and ready */
  ready: boolean;
  /** Optional root path for loading polyfill bundles */
  root?: string | TrustedScriptURL;
  /** Register callback to run after polyfills load (async only) */
  waitFor(callback: WaitForCallback): void;
  /** Internal method for batching custom element upgrades */
  _batchCustomElements(): void;
}

Usage Examples:

<!-- Synchronous loading -->
<script src="webcomponents-loader.js"></script>
<script type="module" src="my-element.js"></script>

<!-- Asynchronous loading -->
<script src="webcomponents-loader.js" defer></script>
<script type="module">
  WebComponents.waitFor(() => import('./my-element.js'));
</script>

waitFor Method

Registers callbacks to execute after polyfills are loaded when using asynchronous loading.

/**
 * Register callback to run after polyfills load (async loading only)
 * @param callback - Function to execute, can return a Promise
 */
waitFor(callback: () => void | Promise<any>): void;

type WaitForCallback = () => void | Promise<any>;

Usage Examples:

// Simple callback
WebComponents.waitFor(() => {
  console.log('Polyfills ready!');
});

// Async callback that loads modules
WebComponents.waitFor(async () => {
  if (!window.fetch) {
    await import('whatwg-fetch');
  }
  return import('./my-element.js');
});

// Multiple callbacks (processed in order)
WebComponents.waitFor(() => import('./element-a.js'));
WebComponents.waitFor(() => import('./element-b.js'));

Root Path Configuration

Configures the base path for loading polyfill bundles when inlining the loader or using custom deployment paths.

/**
 * Optional root path for loading polyfill bundles
 * Must be set before the loader script runs
 * When using Trusted Types, should be a TrustedScriptURL
 */
interface WebComponents {
  root?: string | TrustedScriptURL;
}

Usage Examples:

<!-- Set root path for custom deployment -->
<script>
  window.WebComponents = window.WebComponents || {};
  window.WebComponents.root = '/assets/webcomponents/';
</script>
<script src="inline-webcomponents-loader.js"></script>

<!-- With Trusted Types -->
<script>
  window.WebComponents = window.WebComponents || {};
  // Assume policy is a TrustedTypePolicy
  window.WebComponents.root = policy.createScriptURL('/assets/webcomponents/');
</script>

Feature Detection

The loader performs automatic detection of browser capabilities to determine which polyfills to load.

Detected Features:

  • Shadow DOM: attachShadow and getRootNode in Element.prototype
  • Custom Elements: Native window.customElements API
  • Template: HTMLTemplateElement with proper content property and cloning
  • Platform Features: Promise, Array.from, URL, Symbol constructors

Override Options:

// Force ShadyDOM polyfill even if native Shadow DOM is available
window.ShadyDOM = { force: true };

// Force Custom Elements polyfill even if native implementation exists
window.customElements = { forcePolyfill: true };

Bundle Loading Logic

The loader selects bundles based on detected features:

  • webcomponents-sd-ce-pf.js: Full bundle for IE 11 (all features missing)
  • webcomponents-sd-ce.js: Shadow DOM + Custom Elements for older browsers
  • webcomponents-sd.js: Shadow DOM only for browsers with native Custom Elements
  • webcomponents-ce.js: Custom Elements only for browsers with native Shadow DOM
  • No bundle: Modern browsers with full native support

Trusted Types Support

For Content Security Policy compliance with Trusted Types:

/**
 * CSP Trusted Types support
 * Allow 'webcomponents-loader' policy name in CSP header
 */
// CSP Header example:
// Content-Security-Policy: trusted-types webcomponents-loader;

// The loader automatically creates and uses a trusted types policy
// No additional configuration needed unless setting WebComponents.root

Usage with Custom Root:

// WebComponents.root should be a TrustedScriptURL when using Trusted Types
const policy = trustedTypes.createPolicy('my-policy', {
  createScriptURL: (url) => url
});
window.WebComponents = { 
  root: policy.createScriptURL('/assets/webcomponents/')
};

Loading Modes

Synchronous Loading

Loader runs immediately when encountered, uses document.write() for bundle injection.

<!-- Synchronous mode -->
<script src="webcomponents-loader.js"></script>
<!-- Custom elements scripts can be loaded immediately after -->
<script type="module" src="my-element.js"></script>

Asynchronous Loading

Loader runs after DOM is ready, requires waitFor() for dependent scripts.

<!-- Asynchronous mode -->
<script src="webcomponents-loader.js" defer></script>
<script type="module">
  WebComponents.waitFor(() => {
    // Guaranteed that polyfills are ready
    return import('./my-element.js');
  });
</script>

Error Handling

// Listen for loading errors
const script = document.createElement('script');
script.src = 'webcomponents-loader.js';
script.addEventListener('error', () => {
  console.error('Failed to load Web Components polyfills');
});

Bundle loading errors are thrown as JavaScript errors with descriptive messages indicating the failed bundle URL.