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

Hot module replacement #217

Open
LarsDenBakker opened this issue Nov 24, 2020 · 4 comments
Open

Hot module replacement #217

LarsDenBakker opened this issue Nov 24, 2020 · 4 comments

Comments

@LarsDenBakker
Copy link

Hi there! At open-wc we started working on hot module replacement with es module workflows: https://open-wc.org/docs/development/hot-module-replacement/

So far it works for class based components. We're now looking into how we can support this for function based components.

The idea is that the web component base class implements a static and/or instance hotReplaceCallback function which does the actual replacement. Since you don't want this code to end up in production, projects can make it available through a module which patches the base class.

Since haunted in the end creates a class, I was hoping to do the same here. However one issue I ran into is that the class is created in a closure, so I can't inject any code into it. Also, the renderer function is only available within the closure.

I made some modifications to the source code and the basic features are working, so that looks promising. I did run into some issues with preserving state between replacements, so that would be something to look into.

Is this something that would be interesting to support in haunted?

@matthewp
Copy link
Owner

Hey Lars, thanks for starting the discussion. Is there a reason why you can't do something like this?

import { component } from 'haunted';
import hot from 'hot-web-components';

function App() {
 ...
}

const AppElement = hot(component(App));

ie, wrap the class that component() creates?

@LarsDenBakker
Copy link
Author

LarsDenBakker commented Dec 23, 2020

@matthewp I did some rework, and indeed that's how it works now.

I got it working now for Haunted using a small patch: https://github.com/open-wc/open-wc/blob/master/packages/dev-server-hmr/src/presets/haunted.js#L3

Ideally I would like to patch the hotReplacedCallback onto some base class, would it possible to expose this from within Haunted? I could patch it onto each haunted component individually, but a user might be using multiple component base classes so we'd have to detect that something is a haunted component which makes things more complicated.

A bigger problem is updating the scheduler with a new renderer. Would it be ok to expose the renderer as a static field on the class? Then I could grab it there. I was able to work around it by instantiating a temporary element and getting it from the instance.

@matthewp
Copy link
Owner

Ideally I would like to patch the hotReplacedCallback onto some base class, would it possible to expose this from within Haunted?

Not sure I follow, what change are you suggesting?

A bigger problem is updating the scheduler with a new renderer. Would it be ok to expose the renderer as a static field on the class?

Yeah that's fine, but the scheduler is a privatish field at the moment. We should probably make it public if library are going to depend on it.

@pyrossh
Copy link

pyrossh commented Jun 7, 2021

@LarsDenBakker Don't know if you are still looking into it. This is how I got esm hmr working in my system.

const tag = 'my-counter';
const Module = await import("/assets/my-counter.js");
document.querySelectorAll(tag).forEach((node) => {
  const Scheduler = class extends BaseScheduler {
      constructor(renderer, frag, host) {
          super(renderer, host || frag);
          this.frag = frag;
      }
      commit(result) {
          render(result, this.frag);
      }
  }
  node._scheduler = new Scheduler(Module.default, node);
  node.connectedCallback();
}

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

No branches or pull requests

3 participants