nuxt / nuxt

The Intuitive Vue Framework.
https://nuxt.com
MIT License
54.53k stars 4.99k forks source link

HMR does not pick up updates to data #12822

Closed radusuciu closed 1 year ago

radusuciu commented 2 years ago

Environment

Running on WSL but have had the same issue in a containerized application..

Tested in latest Firefox and Chrome with identical results.

Nuxt CLI v3.0.0-27288761.d3fb512
RootDir: ...
Nuxt project info:

Reproduction

https://github.com/radusuciu/nuxt3-app

repro

Describe the bug

Updated data is not picked up by HMR. Updating the template is. Data updates are reflected after a full refresh only.

Potentially related to nuxt/nuxt.js#11956 but I don't see any errors and it isn't sporadic - it just doesn't work even though Vite does seem to pick up the updates judging by the "Vite server built in XXms" logs messages and "[vite] hot updated: /app.vue" output in the console.

Additional context

I have no issues with HMR in nuxt2, nor if I use vite by itself.

Logs

No response

ilya-adnymics commented 2 years ago

I have the same issue - using npx nuxi init pure-nuxt3 to create a fresh nuxt 3 project and then changing app.vue to

<template>
  <div>
    {{ counter }}
    <NuxtWelcome />
  </div>
</template>

<script setup>
const counter = 1;
</script>

Behavior is the same as described by @radusuciu - updating template works immediately, but whenever I change counter value, it's not updated, only after full page refresh. Pure vite project (created via npm init vite-app pure-vite) doesn't have this issue, both template and script changes are picked up immediately.

radusuciu commented 2 years ago

Thanks for the validation, was feeling a little crazy that I was the only one with the issue despite my being able to reproduce it consistently.. in fact I can't NOT reproduce it šŸ¤£

danielroe commented 2 years ago

I can't reproduce this. Are you still experiencing it?

ilya-adnymics commented 2 years ago

I still can reproduce, here's a smallest repo with reproduction (includes brief instructions in Readme). Probably I'm doing something wrong/missing some config? Cause it's really easy to reproduce for me.

danielroe commented 2 years ago

Would you provide some more info about your setup? Are you using Windows, for example?

CleanShot 2022-04-06 at 12 20 47

ilya-adnymics commented 2 years ago

Ok, so it's related to setup/environment somehow it seems, already better :smile: Thank you for looking into it! I'm using Ubuntu 21.10 (Python 3.8.12, if that's somehow relevant, cause I saw node-gyp related messages during installation).

Just to show you that I can see it on my Ubuntu :) hmr

I tried running it on another machine (with MacOs) - and the issue is not reproducible there. If you have any ideas on what to try, please feel free to share, I'll post here the results

danielroe commented 2 years ago

Oh, I believe you, even without the video proof! šŸ˜‰

What is your full directory name on the Ubuntu box? If there's any way you can confirm other dependencies are the same, such as node & package manager version, that would be great. However, my instinct is that this might be a watcher issue. Are you getting any notification in your browser that a HMR has taken place?

ilya-adnymics commented 2 years ago

To keep you updated: full path to app.vue is "/home/ilya/Personal/hmr-issue/app.vue" Node version is "v16.14.2", npm is "8.6.0". I do see the HMR update message in dev tools console ([vite] hot updated: /app.vue) for both types of update, no errors or warnings. I checked the network traffic and I see the updated script coming in response to http://localhost:3000/_nuxt/app.vue?import&t=1649251053215, i.e. the value is inside the payload, so the watcher gets it (right?): image

I'll keep digging.

danielroe commented 2 years ago

No chance you have any service workers running? Could you try a different browser or an incognito window?

ilya-adnymics commented 2 years ago

I tried running in different browser/incognito - still reproducible. What I've noticed is

export const _rerender_only = true

line in the hot reload script above (line 32 on screenshot above).

I've found where this line is added in @vitejs/plugin-vue:

    if (prevDescriptor && isOnlyTemplateChanged(prevDescriptor, descriptor)) {
      output.push(`export const _rerender_only = true`);
    }

I added logging inside isOnlyTemplateChanged and it shows that scriptSetup.content is always the same for both prevDescriptor and descriptor.

I added the same log on my MacOs box and the script content is different (as it should be) on each update. I think I'm onto something with this, need to check how these descriptors are created and cached in plugin-vue.

ilya-adnymics commented 2 years ago

Ok, @danielroe, your instinct was right after all:

my instinct is that this might be a watcher issue

I kept digging inside @vitejs/plugin-vue and found out that if I add a 100ms sleep inside handleHotUpdate function after file is read, the autoupdates start working. Then I've found this issue, and although it mentions Windows (this was also your instinct I guess, since you asked if I have Windows), the fix worked for me in Ubuntu:

// nuxt.config.ts
export default defineNuxtConfig({
  vite: {
    server: {
      watch: {
        usePolling: true,
      },
    },
  },
});

After I set usePolling to true, it started working as expected. Thank you for your help, I guess this can be closed after @radusuciu confirms.

danielroe commented 2 years ago

Great debugging - thank you for all your hard work! I wonder if there is any environment cue that we can pick up on to enable this by default on affected environments... Or add it to the docs šŸ¤”

ilya-adnymics commented 2 years ago

I don't know, TBH. Pure vite solution works as expected, without explicitly setting the usePolling to true. Could this be related to these fixes: https://github.com/vitejs/vite/commit/36340421f9ee808e4e08240e0b99ccfca1005117?

ghost commented 2 years ago

Ok, @danielroe, your instinct was right after all:

my instinct is that this might be a watcher issue

I kept digging inside @vitejs/plugin-vue and found out that if I add a 100ms sleep inside handleHotUpdate function after file is read, the autoupdates start working. Then I've found this issue, and although it mentions Windows (this was also your instinct I guess, since you asked if I have Windows), the fix worked for me in Ubuntu:

// nuxt.config.ts
export default defineNuxtConfig({
  vite: {
    server: {
      watch: {
        usePolling: true,
      },
    },
  },
});

After I set usePolling to true, it started working as expected. Thank you for your help, I guess this can be closed after @radusuciu confirms.

------------------------------
- Operating System: `Windows_NT`
- Node Version:     `v16.15.0`
- Nuxt Version:     `3.0.0-rc.1`
- Package Manager:  `npm@8.5.5`
- Builder:          `vite`
- User Config:      `typescript`, `vite`
- Runtime Modules:  `-`
- Build Modules:    `-`
------------------------------

Same problem here (on Windows), your solution solves the problem , thx

kevinmarrec commented 2 years ago

Encountered same issue (I'm on WSL2 but my code is on the Subsystem), fixed with vite.server.watch.usePolling.

Reproduction

<script setup>
const data = ref('a')
</script>

<template>
  <div>
    {{ data }}
  </div>
</template>

Then changes ref('a') to ref('b') in your editor, and save.

On my computer, it won't correctly trigger HMR client side.

pi0 commented 2 years ago

Thanks for sharing reproductions. I can confirm the same issue on WSL2 and also normal Linux servers and windows. HMR only works fine on a macOS laptop with fsevents.

An interesting finding is that native watcher, works but only for one instance. Disabling server [watcher] with ssr: false, client watcher and HMR start to work.

radusuciu commented 2 years ago

Ok, @danielroe, your instinct was right after all:

my instinct is that this might be a watcher issue

I kept digging inside @vitejs/plugin-vue and found out that if I add a 100ms sleep inside handleHotUpdate function after file is read, the autoupdates start working. Then I've found this issue, and although it mentions Windows (this was also your instinct I guess, since you asked if I have Windows), the fix worked for me in Ubuntu:

// nuxt.config.ts
export default defineNuxtConfig({
  vite: {
    server: {
      watch: {
        usePolling: true,
      },
    },
  },
});

After I set usePolling to true, it started working as expected. Thank you for your help, I guess this can be closed after @radusuciu confirms.

Hi, sorry for abandoning issue there but I haven't used nuxt since this (partly because of this bug and partly because I wanted to stick with just vite for simplicity since I was already committed to using Django and I'm happy enough with using that to bootstrap data where needed).

I wouldn't consider usePolling to be a solution though since polling is generally less responsive.

kevinmarrec commented 2 years ago

As an alternative of vite.server.watch.usePolling option, you can add this to your Shell profile (.bashrc/.zshrc, ...) :

# Workaround for Chokidar Watcher
export CHOKIDAR_USEPOLLING=1

This will do the same but be applied for every project through this environment variable.

This can be suitable until we find a better solution to this issue.

Aybee5 commented 2 years ago

I am also experiencing the same problem on Ubuntu 20.04, unfortunately, this doesn't work for me the vite.server.watch... however works

As an alternative of vite.server.watch.usePolling option, you can add this to your Shell profile (.bashrc/.zshrc, ...) :

# Workaround for Chokidar Watcher
export CHOKIDAR_USEPOLLING=1

This will do the same but be applied for every project through this environment variable.

This can be suitable until we find a better solution to this issue.

pYr0x commented 2 years ago

i run into the same issue.

i have this simple Vue Component

<script setup>
const foo = useState('foo', () => 1);
</script>

<template>
  {{foo}}
</template>

if i change foo, HMR will not update the browser. i am on windows 10 and use nuxt3 my config looks like this:

export default defineNuxtConfig({
  ssr: false,
  vite: {
    server: {
      watch: {
        usePolling: true
      }
    }
  },
  buildModules: [
    '@pinia/nuxt',
  ],
})
ihteshamqazi commented 2 years ago

I have the same issue. I have tailwind installed with nuxt3 app. When i change the class of any html element, the hmr will not update the browser. Until i restart server. My nuxtconfig is: serverMiddleware: [ // Will register file from project server-middleware directory to handle /server-api/* requests { path: "/api", handler: "~/server/api/index.ts" }, ], vite: { server: { watch: { usePolling: true, }, }, }, ssr: false, css: ["~/assets/css/app.css"], build: { postcss: { postcssOptions: { plugins: { tailwindcss: {}, autoprefixer: {}, }, }, }, },

Can someone help please ?

madebyfabian commented 1 year ago

Is this still an issue with current stable nuxt releases? Or can it be closed?

radusuciu commented 1 year ago

I just verified that this is fixed with the latest version of nuxt! Thank you!