A utility that prevents duplicate custom element registration errors by monkey-patching window.customElements.define
npx @tessl/cli install tessl/npm-lrnwebcomponents--deduping-fix@8.0.0Deduping Fix is a utility package that solves a critical web components platform issue where attempting to define the same custom element twice causes a hard failure. The package provides a non-breaking solution by monkey-patching the global window.customElements.define function to check for existing element definitions before attempting registration.
npm install @lrnwebcomponents/deduping-fiximport '@lrnwebcomponents/deduping-fix';For CommonJS environments:
require('@lrnwebcomponents/deduping-fix');The package works entirely through side effects when imported. No explicit API calls are needed:
import '@lrnwebcomponents/deduping-fix';
// Now safe to define custom elements multiple times
customElements.define('my-element', class extends HTMLElement {
// Element implementation
});
// This won't throw an error, just logs a warning
customElements.define('my-element', class extends HTMLElement {
// Different implementation - will be ignored with warning
});Deduping Fix works by intercepting the native Custom Elements API:
window.customElements.define with a wrapper functioncustomElements.get() to check for existing definitionsPrevents duplicate custom element registration errors by intercepting and modifying the global customElements.define function.
/**
* Modified window.customElements.define function that prevents duplicate registrations
* @param name - The name of the custom element to define
* @param cl - The custom element constructor class
* @param conf - Optional configuration object for the custom element
*/
window.customElements.define(
name: string,
cl: CustomElementConstructor,
conf?: ElementDefinitionOptions
): void;Behavior Changes:
DOMException: "Failed to execute 'define' on 'CustomElementRegistry'"console.warn("${name} has been defined twice") and continue executionUsage Examples:
import '@lrnwebcomponents/deduping-fix';
// First definition - works normally
customElements.define('my-button', class MyButton extends HTMLElement {
constructor() {
super();
this.innerHTML = '<button>Click me</button>';
}
});
// Second definition - logs warning instead of throwing error
customElements.define('my-button', class AnotherButton extends HTMLElement {
constructor() {
super();
this.innerHTML = '<button>Different button</button>';
}
});
// Console output: "my-button has been defined twice"Common Use Cases:
// Development hot-reloading scenarios
import '@lrnwebcomponents/deduping-fix';
import './my-component.js'; // May be reloaded multiple times
// Dynamic imports with timing issues
import '@lrnwebcomponents/deduping-fix';
Promise.all([
import('./component-a.js'),
import('./component-b.js'), // Both might define same element
]).then(() => {
// No registration conflicts
});
// Legacy platform integration
import '@lrnwebcomponents/deduping-fix';
// Import multiple libraries that might define conflicting elements
import 'legacy-component-library-1';
import 'legacy-component-library-2';The package handles duplicate custom element definitions gracefully:
window object)/**
* Original customElements.define function reference stored before modification
*/
declare const _customElementsDefine: (
name: string,
constructor: CustomElementConstructor,
options?: ElementDefinitionOptions
) => void;
/**
* Standard Custom Elements API types
*/
interface CustomElementConstructor {
new (): HTMLElement;
}
interface ElementDefinitionOptions {
extends?: string;
}