Skip to content

Instantly share code, notes, and snippets.

@treshugart
Last active August 11, 2017 23:33
Show Gist options
  • Save treshugart/366812a76b89cb68b87745e4196a6351 to your computer and use it in GitHub Desktop.
Save treshugart/366812a76b89cb68b87745e4196a6351 to your computer and use it in GitHub Desktop.
Web component that allows you to define a split point in your code at the component level.

Trying to attempt a similar pattern in Web Components that was done here in React. Props to James Kyle for the original idea :)

import lazy from './lazy';
// Define a code-split point for the ./hello module.
const Split = lazy(() => import('./hello'));
customElements.define('x-hello-split', Split);
// The ./hello module is only loaded / defined once it's actually used.
document.body.innerHTML = `<x-hello-split>You</x-hello-split>`;
export default class extends HTMLElement {
connectedCallback () {
this.attachShadow({ mode: 'open' })
.innerHTML = 'Hello, <strong><slot>World</slot></strong>!';
}
}
// We really don't need this, but it makes defining split points easier because
// we don't need to always choose a name for the component we're splitting at.
import { define } from 'skatejs';
// Returns a custom element that will be lazy loaded when it is used in HTML.
export default function (load, { loading = 'Loading...', name } = {}) {
return class extends HTMLElement {
connectedCallback () {
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = `<slot name="loading">${loading}</slot>`;
load().then(ce => {
// Handle ES2015 and CommonJS / AMD
const CustomElement = ce.default || ce;
// Only uses Skate to choose a default name for the component since the
// name of the loaded component matters less than the split name given
// by the consumer. This lessens the API surface the consumer needs to
// care about.
if (name) {
customElements.define(name, CustomElement);
} else {
define(CustomElement);
}
// Create the custom element and add a slot to it so that the consumer
// content is distributed into it.
const customElement = new CustomElement();
const consumerSlot = document.createElement('slot');
customElement.appendChild(consumerSlot);
// Remove the loading indicator and add the loaded custom element.
shadowRoot.innerHTML = '';
shadowRoot.appendChild(customElement);
});
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment