Trying to attempt a similar pattern in Web Components that was done here in React. Props to James Kyle for the original idea :)
Last active
August 11, 2017 23:33
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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>`; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export default class extends HTMLElement { | |
connectedCallback () { | |
this.attachShadow({ mode: 'open' }) | |
.innerHTML = 'Hello, <strong><slot>World</slot></strong>!'; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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