Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updating Element Registration. #820

Open
pshihn opened this issue Jun 22, 2019 · 8 comments
Open

Updating Element Registration. #820

pshihn opened this issue Jun 22, 2019 · 8 comments

Comments

@pshihn
Copy link

pshihn commented Jun 22, 2019

Are there any discussions to support updating the implementation of a custom element definition? (Searched and did not spot anything obvious)

Something like this:

customElements.define('my-element', MyElement);
// ...
// some time later...
customElements.redefine('my-element', MyElement2);

I can see a lot of issues with this, the obvious one being what happens to existing elements that are already in the DOM - are they recreated? left alone with old implementation? Or just turned into no-ops?

Use case

Let's say, I have a web component that is sitting on a page with long life time .- say email client or stock dashboard which people have open all the time and rarely 'refresh'.

The client code at some point realized there's a new version of my-element available and I want to upgrade it to the latest without reloading the whole page.

This is particularly useful if there's some sort of change in the protocol/api the custom element may use with the back end.

@annevk
Copy link
Collaborator

annevk commented Jun 24, 2019

Have you tried implementing this in user space via a proxy class of sorts? Introducing "replace" semantics at the DOM-level would be a quite significant undertaking.

@rniwa
Copy link
Collaborator

rniwa commented Jun 25, 2019

Given most of native apps don't have the ability to monkey patch itself while running, I have a hard time believing that many web apps would opt to do this. Why can't such an app periodically reload itself (e.g. once a week)? Or if not, use some kind of versioning so that new elements are of a different name? I fully agree with @annevk's statement above that the need for a feature of this immense complexity and cost would need to be very well vetted in user land first.

@pshihn
Copy link
Author

pshihn commented Jun 25, 2019

Refreshing the page is not really an option.

In any case, I didn't think this would be easily implemented. It was more about what people's thoughts were about the idea and if there was something obvious I was missing

@mantou132
Copy link

mantou132 commented Nov 22, 2020

Support for redefine will make hot replacement easy to implement.

class MyElement extends HTMLElement {}
customElements.define('my-element', MyElement);

...
if (customElements.get('my-element')) {
  customElements.redefine('my-element', MyElement2);
  customElements.upgrade(document.documentElement);
}

@pshihn
Copy link
Author

pshihn commented Nov 23, 2020

hot replacement with new version of the code on a page as well, not just for development. In some cases a better option than asking the user to refresh the page. It's tricky though, because nodes on the page already be part of the DOM. Initially I thought of this as only for new nodes.

@bahrus
Copy link

bahrus commented Nov 25, 2020

Given most of native apps don't have the ability to monkey patch itself while running, I have a hard time believing that many web apps would opt to do this.

One significant difference between native apps and web apps, is that web apps tend to load progressively. It would be nice to be able to create a "basic" version of a component, and a "deluxe" version with far more bells and whistles.

Imagine a simple grid component, for example, that just shows data in a tabular format, but then could be replaced by a fully functional grid featuring sorting, charting, etc., once all the dependencies are downloaded.

There are some tricky issues here, just from a "spec" point of view -- like could property values or other state settings be transferred?

But just wanted to throw out another use case.

@trusktr
Copy link

trusktr commented Mar 22, 2021

Are there any discussions to support updating the implementation of a custom element definition? (Searched and did not spot anything obvious)

@pshihn See #754. It would be great if it were left opened.

Have you tried implementing this in user space via a proxy class of sorts?

@annevk That requires the CE author to write a framework rather than just using plain CEs. It would take the fun out of writing CEs.

Given most of native apps don't have the ability to monkey patch itself while running, I have a hard time believing that many web apps would opt to do this.

Of all systems that exist, the web may be the one that is best at exactly this.

I think it may be great to allow devs to undefine elements, so they can then redefine them with new classes. This is also related to the ability to dynamically change the registry that is associated with a ShadowRoot (related: #914 and #907).

The ability to update applications without a full-refresh is a super compelling use case. If web could do it, and native can't, in my opinion that gives web a far superior advantage. Just because native can't doesn't mean web shouldn't.

@getflourish
Copy link

getflourish commented Oct 18, 2021

I agree, this would be super useful not only for HMR, but really any authoring tool that wants to build on top of CustomElements.

I think it’s the nature of JavaScript to be open to modification at runtime. We can already "upgrade" elements once, so why not another time? Why can’t we point the constructor to different classes?

I think I’ve found a way to create custom elements with the same name, but different implementations. It obviously involves some hijacking but it seems to work as far as I can tell. I need to do more tests and see where limitations are.

I didn't want to monkey-patch the customElements registry directly with a new method as proposed here, so my interim solution is a "custom" registry for defining elements that will internally use the original registry:

myElements.define('my-element', MyElement1)
myElements.define('my-element', MyElement2)

When inserting custom elements again, they will use the new implementation. Upgrading existing custom elements with a new implementation can be done using standard DOM node replacements. I will follow-up with some code soon.

Has there been any prior work done in that direction? @pshihn did you follow up on that at all?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants