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 reload fails when using Import wrappers #96

Open
paulnta opened this issue Apr 28, 2021 · 5 comments · May be fixed by #112
Open

Hot reload fails when using Import wrappers #96

paulnta opened this issue Apr 28, 2021 · 5 comments · May be fixed by #112

Comments

@paulnta
Copy link

paulnta commented Apr 28, 2021

I have a Nuxt project and I'm trying to understand why import wrappers such as hydrateWhenVisible don't work well with hot reload. When I edit a lazy hydrated component, some errors are triggered and the component seems to lose its props.

Steps to reproduce:
You can use this codesandbox: https://codesandbox.io/s/vue-lazy-hydration-hot-reload-issue-vfrpm

  • No problem when editing pages/index.vue
  • But editing HelloWorld.vue will trigger the following errors (you may have to edit the template a few times before it fails)
    Cannot read property 'message' of undefined
    Failed to execute 'unobserve' on 'IntersectionObserver'
    

pages/index.vue

<template>
    <HelloWorld :content="{ message: 'hello world' }" />
</template>

<script>
import { hydrateWhenVisible } from "vue-lazy-hydration";

export default {
  components: {
    HelloWorld: hydrateWhenVisible(() => import("~/components/HelloWorld")),
  },
};
</script>

components/HelloWorld.vue

<template>
  <div>
    <h1>{{ content.message }}</h1>
    <!-- Editing this template will fail on hot reload: `content` is undefined -->
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  props: {
    content: Object,
  },
};
</script>

Thanks in advance 🙏

@paulnta
Copy link
Author

paulnta commented Apr 29, 2021

One additional info is that this issue happens only with v2

@paulnta
Copy link
Author

paulnta commented Sep 9, 2021

I looked more into this issue and it seems related to the way the HoC render function (makeHydrationBlocker) is implemented: attrs: this.$attrs doesn't forward props correctly during hot reload.

render(h) {
return h(this.Nonce, {
attrs: this.$attrs,
on: this.$listeners,
scopedSlots: this.$scopedSlots,
}, this.$slots.default);

I could reproduce the same problem by creating a minimal HoC that just wraps a component and forward all props. During hot-reload the component being wrapped loses all its props.

function WithLogger(Component) {
  return {
    render(h) {
      console.log('render', Component.name)
      return h(Component, {
        attrs: this.$attrs,
      });
    },
  };
}

Check this sandbox: https://codesandbox.io/s/vue-hot-reload-issue-with-hoc-2q1u6?file=/pages/index.vue

However, passing a copy of $attrs fixes the problem. If someone can explain why 🤷‍♂️ ?

h(Component, {
  attrs: Object.assing({}, this.$attrs)
})

I tested this fix in vue-lazy-hydration and It works too 👌 .

paulnta added a commit to paulnta/vue-lazy-hydration that referenced this issue Sep 10, 2021
@paulnta paulnta linked a pull request Sep 10, 2021 that will close this issue
@regenrek
Copy link

Hi @paulnta what error message did you get when this happened? I think I'm having the same issue. Will try your possible fix.

Regards

@paulnta
Copy link
Author

paulnta commented Sep 30, 2021

@regenrek the error happen because the component props are lost sometimes after hot reload. So you may have an error like Cannot read property '<name of a property>' of undefined. That's what I got first.

And this error triggered the next one Failed to execute 'unobserve' on 'IntersectionObserver'. This happens because the component fails to render and Vue turns it into a <!-- --> comment which is something vue-lazy-hydration doesn't expect.

Yes please, tell me if you have the same problem and if the fix works.

@paulnta
Copy link
Author

paulnta commented Sep 30, 2021

In the current version we are using vue-lazy-hydration@1.0.0-beta.14, import wrappers don't work with Nuxt fetch hook. So we would like to upgrade, but the current version has this issue which is not an ideal DX.

While waiting for a fix, I'll probably switch to <LazyHydrate when-visible>....</LazyHydrate>. However, I noticed some important performance differences. With import wrappers, the component's bundle is also lazily evaluated. This has a positive impact on TBT.

@maoberlehner I know you are busy (based on your GH status 😄 ), but it would be amazing if you could have a look at the PR.

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

Successfully merging a pull request may close this issue.

2 participants