Changes To Web Component Support In CUE

HTML Imports support will soon be removed from Chrome

CUE currently imports web components using HTML Imports. HTML Imports has been deprecated by Google Chrome and support for it will be removed in version M73 of Chrome, around March 2019.

To remedy this, CUE will also support loading web components as ECMAScript (ES) modules from the following versions:

  • CUE 2.8.14
  • CUE 2.9.6
  • CUE 3.0.6
  • CUE 3.1.6
  • CUE 3.2.3

CUE will continue to support web components via HTML imports until support for it has been removed from Google Chrome.

What does that mean for you?

To continue using web components in CUE following the Google Chrome M73 update, you must update CUE to one of the versions listed above and modify your web components so they are loaded as ES modules.

Updating CUE

The first step to update CUE. You can safely update CUE without changing any of your web components.

Loading web components as ES modules

This section describes how to modify your web components so that they are loaded as ES modules after you have updated CUE.

Your existing web components are plain HTML files loaded using HTML Import. To load a web component as an ES module it must be a JavaScript file instead.

Below you will find:

  • An example of an HTML web component that can be loaded using HTML Imports
  • A corresponding example showing what the component needs to look like in order to be imported as an ES module.
  • A CUE config example showing how current HTML web components are configured
  • A corresponding CUE config example showing how ES module web components must be configured
     

HTML Import: my-component.html

<template id="component">
<style>
:host { width: 100%; display: block; } /* Styles the web component tag */
</style>
<!-- Add your web component HTML here -->
</template>
<!-- Template for the web component icon (if required) -->
<template id="icon">
<!-- Add your web component icon HTML here -->
</template>
<script>
(function(window, document) {
const thisDoc = (document._currentScript || document.currentScript).ownerDocument;
/**
* Creating the web component
*/
class MyComponent extends HTMLElement {
constructor() {
super();
const template = thisDoc.querySelector('template#component').content;
let shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.appendChild(template.cloneNode(true));
}
connectedCallback() {
console.log('The CUE interface of the web component:', this.cueInterface);
// The web component is now attached.
// Add your logic here.
}
}
customElements.define('my-component', MyComponent);
/**
* Creating the icon (if required)
*/
class MyComponentIcon extends HTMLElement {
constructor() {
super();
const template = thisDoc.querySelector('template#icon').content;
let shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.appendChild(template.cloneNode(true));
}
connectedCallback() {
console.log('The CUE interface of the icon:', this.cueInterface)
// The icon is now attached.
// Add your logic here.
}
}
customElements.define('my-component-icon', MyComponentIcon);
})(window, document);
</script>

ES module: my-component.js

/**
* Creating the web component
*/
class MyComponent extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<style>
:host { width: 100%; display: block; } /* Styles the web component tag */
</style>
<!-- Add your web component HTML here -->
`;
}
connectedCallback() {
console.log('The CUE interface of the web component:', this.cueInterface);
// The web component is now attached.
// Add your logic here.
}
}
customElements.define('my-component', MyComponent);
/**
* Creating the icon (if required)
*/
class MyComponentIcon extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `<!-- Add your web component HTML here -->`;
}
connectedCallback() {
console.log('The CUE interface of the icon:', this.cueInterface)
// The icon is now attached.
// Add your logic here.
}
}
customElements.define('my-component-icon', MyComponentIcon);

The main difference between the two styles is one is an HTML file and the other is a JavaScript file.

You cannot declare <template> tags directly in an ES module web component. Instead, the HTML must be added directly to the shadow root, by using innerHTML, for example.

Once you have made these changes to your web component, all you need to do is to instruct CUE to load the web component as an ES module by changing your config file settings.

HTML Import: config.yaml

sidePanels:
- id: "my-component"
name: "MyComponent"
directive: "cf-custom-panel-loader"
webComponent:
htmlImport: "http://www.example.com/webcomponents/my-component.html"
icon: "my-component-icon"
mimeTypes: []
homeScreen: true
metadata: []
active: false
order: 801

ES Module: config.yaml

sidePanels:
- id: "my-component"
name: "MyComponent"
directive: "cf-custom-panel-loader"
webComponent:
modulePath: "http://www.example.com/webcomponents/my-component.js"
icon: "my-component-icon"
mimeTypes: []
homeScreen: true
metadata: []
active: false
order: 801

Further reading

Custom Elements - https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements

HTML Imports - https://www.w3.org/TR/html-imports/

Google Chrome HTML Import status - https://www.chromestatus.com/feature/5144752345317376

Google Chrome release plan - https://www.chromestatus.com/features/schedule

Google’s guide to custom elements - https://developers.google.com/web/fundamentals/web-components/customelements