-
Notifications
You must be signed in to change notification settings - Fork 387
Description
One of our libraries is providing a growing library of custom elements, some of which are quite large and/or rely on other large third-party libraries. We don't really want to load in all these definitions because they aren't necessarily going to be used by developers using the library. To account for this, I wrote a minimal DeferredCustomElement interface that loads in the real definition when the createdCallback is called.
This works fine, though I'm not thrilled about mutating the class later and lifecycle callbacks have to be called from within the original definition. With these issues and some recent changes to the spec—particularly with observedAttributes, which would mean maintaining a list separate from the "real" element definition—, it's becoming less likely that this is going to hold up well in the long run.
One solution would be to require anyone using our custom elements to import the modules in their code. This has the following disadvantages:
- Requires at least one script in the page to import the module if the behaviour is required, even if the API isn't used.
- Introduces another divergence from typical HTML elements, further reducing transparency.
- Changes to the module location can't be made without breaking existing code.
importwould mean waiting until the module loads in before running the rest of the script.System.import()adds an extra wrapper around a block of code and any custom elements would need to be created inside that wrapper because of the recent no-upgrade decision.- Either the element's module has to define itself, which impacts portability and reusability, or the author would need to define it correctly.
It would be nice if we could specify a module to load on-demand in the call to defineElement:
// Library code
[ 'element1', 'element2', 'element3' ].forEach(el =>
document.defineElement(`my-${el}`, { module: `./${el}.js` }))// Example module code
export default class Element1 extends HTMLElement {
// ...
}This has the additional advantage that elements created with document.createElement() can be safely upgraded (the element's definition would be responsible for letting the author know its API is ready). I think it's certainly more foolproof, which is a boon considering most of our library users aren't "pro" JavaScript developers.