The custom-elements-es5-adapter.js provides compatibility for ES5-style custom element classes when using transpiled code with native Custom Elements implementations.
Compatibility shim that allows ES5-style custom element classes to work with native Custom Elements.
/**
* Include custom-elements-es5-adapter.js before defining custom elements
* Automatically wraps ES5 constructor functions for native Custom Elements compatibility
* Required when serving ES5 code to browsers with native Custom Elements support
*/
// <script src="custom-elements-es5-adapter.js"></script>
// The adapter automatically patches the native customElements.define method
// No direct API - works transparently with custom element definitionsUsage Examples:
<!-- Load adapter first -->
<script src="custom-elements-es5-adapter.js"></script>
<!-- Then load ES5-compiled custom elements -->
<script src="my-element-es5.js"></script>
<!-- Elements work normally -->
<my-element></my-element>Understanding when and why the ES5 adapter is needed.
/**
* Problem: ES5 classes cannot properly extend native ES6 classes like HTMLElement
* Native Custom Elements API requires ES6 class syntax for proper prototype chain
*
* Without adapter:
* - ES5 custom elements fail on browsers with native Custom Elements
* - TypeError: Class constructor HTMLElement cannot be invoked without 'new'
*
* With adapter:
* - ES5 constructor functions are automatically wrapped
* - Proper prototype chain is established
* - Custom elements work correctly
*/
// ES5 style (problematic without adapter)
function MyElement() {
// This fails with native Custom Elements
return HTMLElement.call(this) || this;
}
MyElement.prototype = Object.create(HTMLElement.prototype);
// ES6 style (works natively)
class MyElement extends HTMLElement {
constructor() {
super();
}
}The adapter automatically detects and wraps ES5 constructor functions.
/**
* The adapter patches customElements.define to detect ES5 constructors
* When an ES5 constructor is detected, it's automatically wrapped
* The wrapping preserves the original constructor's behavior
*/
// Original ES5 custom element
function MyButton() {
var self = HTMLElement.call(this) || this;
self.addEventListener('click', self._handleClick);
return self;
}
MyButton.prototype = Object.create(HTMLElement.prototype);
MyButton.prototype._handleClick = function() {
console.log('Clicked!');
};
// With adapter loaded, this works on native Custom Elements:
customElements.define('my-button', MyButton);Usage Examples:
// Transpiled Babel/TypeScript output (ES5)
var MyElement = /** @class */ (function (_super) {
__extends(MyElement, _super);
function MyElement() {
var _this = _super.call(this) || this;
_this.attachShadow({mode: 'open'});
return _this;
}
return MyElement;
}(HTMLElement));
// Works with adapter
customElements.define('my-element', MyElement);When to include the ES5 adapter in your application.
/**
* Include adapter when:
* - Serving ES5/transpiled code to all browsers
* - Target browsers include both ES5-only and native Custom Elements support
* - Using build tools that compile to ES5 (Babel, TypeScript ES5 target)
*
* Skip adapter when:
* - Serving ES6+ code with differential loading
* - Only targeting browsers without native Custom Elements (IE11, old browsers)
* - Using only the webcomponents-bundle.js (includes adapter functionality)
*/
// Browser support matrix:
// - Chrome 54+: Native Custom Elements, needs adapter for ES5 code
// - Safari 10.1+: Native Custom Elements, needs adapter for ES5 code
// - Firefox 63+: Native Custom Elements, needs adapter for ES5 code
// - IE 11: No native Custom Elements, polyfill handles ES5 codeHow the adapter works with other Web Components polyfills.
/**
* Adapter loading order:
* 1. Load adapter before custom element definitions
* 2. Adapter can be loaded before or after other polyfills
* 3. If using webcomponents-bundle.js, adapter is already included
*/
// Correct loading order
// <script src="custom-elements-es5-adapter.js"></script>
// <script src="webcomponents-loader.js"></script> <!-- Optional -->
// <script src="my-elements.js"></script>
// Or with bundle (adapter included)
// <script src="webcomponents-bundle.js"></script>
// <script src="my-elements.js"></script>Usage Examples:
<!-- Differential loading approach -->
<script type="module" src="my-element-es6.js"></script>
<script nomodule>
// For older browsers, load adapter + ES5 code
document.write('<script src="custom-elements-es5-adapter.js"><\/script>');
document.write('<script src="my-element-es5.js"><\/script>');
</script>
<!-- Universal ES5 approach -->
<script src="custom-elements-es5-adapter.js"></script>
<script src="my-element-es5.js"></script>// webpack.config.js
module.exports = {
entry: {
'es5-adapter': '@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js',
'app': './src/app.js'
},
// Ensure adapter loads before app code
};// tsconfig.json for ES5 output requiring adapter
{
"compilerOptions": {
"target": "es5",
"lib": ["es2015", "dom"],
"experimentalDecorators": true
}
}// .babelrc for ES5 output requiring adapter
{
"presets": [
["@babel/preset-env", {
"targets": {
"browsers": ["ie 11"]
}
}]
]
}File Size:
Runtime Performance:
Loading Strategy:
// The adapter handles common ES5/ES6 compatibility issues automatically
// Manual error handling is rarely needed
try {
customElements.define('my-element', MyES5Element);
} catch (error) {
console.error('Custom element definition failed:', error);
// Fallback to non-custom element implementation
}Common issues the adapter resolves: