[webcomponents] On-demand custom elements using modules (#444)

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.
* `import` would 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`:

```javascript
// Library code
[ 'element1', 'element2', 'element3' ].forEach(el =>
    document.defineElement(`my-${el}`, { module: `./${el}.js` }))
```
```javascript
// 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.

---
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/w3c/webcomponents/issues/444

Received on Wednesday, 16 March 2016 11:12:11 UTC