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

dev-server-hmr makes rendering 2x slower after each rerender #2774

Open
bashmish opened this issue Feb 1, 2024 · 0 comments
Open

dev-server-hmr makes rendering 2x slower after each rerender #2774

bashmish opened this issue Feb 1, 2024 · 0 comments

Comments

@bashmish
Copy link
Member

bashmish commented Feb 1, 2024

Expected behavior

HMR does't add huge performance hit, making every next rerender 2x slower

Actual Behavior

A combination of components makes rendering 2x slower each time.
Reproduction: https://github.com/bashmish/bug-slow-open-wc-hmr => npm i && npm start

Monosnap.screencast.2024-02-01.16-55-01.mp4

Additional context

This is due to the UpdatingElement which get's registered by the HMR logic, because it extends HTMLElement.
In Lit 3 same happens with ReactiveElement.
If you disable the HMR plugin, the UI works fast and consistently fast.

I deliberately added "node_modules/lit-element/node_modules/@lit/reactive-element/**" in the reproduction to include, although in real life my setup is more complex and UpdatingElement is bundled together with MyElement and the bundle is loaded as a single file, so include / exclude file matcher are not helpful as a workaround.

I made this simple commit with a test to illustrate this behavior: e2147a3
This test will fail

  1) babelPluginWcHmr - detecting base class
       global base class:

      AssertionError: expected 'import * as __$wc_hmr$__ from \'/__we…' to equal 'import * as __$wc_hmr$__ from \'/__we…'
      + expected - actual

       if (import.meta.hot) {
         import.meta.hot.accept();
       }
       let Foo = __$wc_hmr$__.register(import.meta, "Foo", class Foo extends MyElement {});
      -;
      -let UpdatingElement = __$wc_hmr$__.register(import.meta, "UpdatingElement", class UpdatingElement extends HTMLElement {});
      -;
      +class UpdatingElement extends HTMLElement {}

      at Context.<anonymous> (packages/dev-server-hmr/test-node/babel/base-class.test.js:13:23)
      at process.processImmediate (node:internal/timers:478:21)

Documentation https://open-wc.org/docs/development/hot-module-replacement/#detecting-web-components says however that:

By default we look for usage of customElements.define and/or classes that derive from HTMLElement directly.

So it seems to be an expected behavior, but not clear why.

Proposal

Some ideas:

  • do not automatically register all classes extending from HTMLElement (not sure why this is done by default? I did see different specs, but they focus on other more specific cases, e.g. with customElements.define, so still not clear to me)
  • add "excludeClass" to specify classes which shouldn't be registered and add UpdatingElement/ReactiveElement to lit presets
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

1 participant