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

[Vite 3] @vitejs/plugin-vue breaks HMR when used with vite-plugin-ssr #9341

Closed
7 tasks done
brillout opened this issue Jul 24, 2022 · 12 comments
Closed
7 tasks done

[Vite 3] @vitejs/plugin-vue breaks HMR when used with vite-plugin-ssr #9341

brillout opened this issue Jul 24, 2022 · 12 comments

Comments

@brillout
Copy link
Contributor

brillout commented Jul 24, 2022

Describe the bug

HMR doesn't work.

== EDIT ==
The root cause seems to be that @vitejs/plugin-vue is not respecting ecosystem query parameters. See discussion below.
=========

I had a quick look at it: the signal is not being sent to the browser.

Note that the socket message {"type":"update","updates":[{"type":"js-update","timestamp":1658677022754,"path":"/pages/index.page.client.vue?extractExportNames&lang.vue" is not enough (it only updates the ?extractExportNames version of the module).

The terminal says:

5:38:42 PM [vite] hmr update /pages/index.page.client.vue?extractExportNames&lang.vue

But that's not correct as it should say:

5:38:42 PM [vite] hmr update /pages/index.page.client.vue?extractExportNames&lang.vue
5:38:42 PM [vite] hmr update /pages/index.page.client.vue

The last line is missing.

Reproduction

https://github.com/brillout/vps-issue-client-only-hmr

System Info

System:
    OS: Linux 5.10 Debian GNU/Linux 10 (buster) 10 (buster)
    CPU: (2) x64 Intel(R) Celeron(R) N4020 CPU @ 1.10GHz
    Memory: 224.54 MB / 2.71 GB
    Container: Yes
    Shell: 5.0.3 - /bin/bash
  Binaries:
    Node: 18.0.0 - ~/.config/nvm/versions/node/v18.0.0/bin/node
    Yarn: 1.22.17 - /usr/local/bin/yarn
    npm: 8.6.0 - ~/.config/nvm/versions/node/v18.0.0/bin/npm
  Browsers:
    Firefox: 97.0.1
  npmPackages:
    @vitejs/plugin-vue: ^3.0.1 => 3.0.1 
    vite: ^3.0.2 => 3.0.2

Used Package Manager

pnpm

Logs

No response

Validations

@AaronBeaudoin
Copy link

AaronBeaudoin commented Jul 28, 2022

Really looking forward to seeing this resolved! Using vite-plugin-ssr isn't quite complete without it because HMR doesn't work at all while rendering a page in SPA (client-only) mode.

@jdpt0
Copy link

jdpt0 commented Jul 28, 2022

Not sure if this is related to the same issue as this, but I'm having issues getting HMR working with the react plugin on Vite 3, client-side only. Weirdly enough, if I change the vite config while hosting, HMR starts to work. Are you able to get the same behavior with Vue?

I'll open a separate issue if they're not related.

@brillout
Copy link
Contributor Author

brillout commented Jul 29, 2022

Also https://twitter.com/youyuxi/status/1552640407057547264.

Not sure if these have the same root cause, but something seems wrong with HMR and Vite 3.

@Demivan
Copy link
Contributor

Demivan commented Jul 29, 2022

Cause:

vite-plugin-ssr module id (url) looks like this:
/pages/index.page.client.vue?extractExportNames&lang.vue

plugin-vue assumes that it is a main vue module because there is no type= in query string and updates it instead of module with id /pages/index.page.client.vue:

const mainModule = modules.find(
(m) => !/type=/.test(m.url) || /type=script/.test(m.url)
)

@Demivan
Copy link
Contributor

Demivan commented Jul 29, 2022

We can either change vite detection of main module or add type={something} to vite-plugin-ssr module ids

@brillout
Copy link
Contributor Author

Ok I see, but I don't think it's vite-plugin-ssr that should add type though, right? Since that's a Vue thing.

From vite-plugin-ssr's side the ?extractExportNames addition does respect prior queries: https://github.com/brillout/vite-plugin-ssr/blob/96531877247328f64a1371b6d4a16a9201c96ccf/vite-plugin-ssr/node/plugin/plugins/extractExportNamesPlugin.ts#L68-L78.

So I'm thinking it's the Vue plugin that can't cope with ?extractExportNames?

@AaronBeaudoin
Copy link

As a user, one of the things I love about vite-plugin-ssr is that it tries to be as framework agnostic as possible. Forcing it to accommodate some type URL parameter specific to Vue SFC files definitely seems like the wrong solution to me.

It just sounds like the URL patterns in plugin-vue are too narrow.

@brillout brillout changed the title [Vite 3] HMR with @vitejs/plugin-vue doesn't work [Vite 3] @vitejs/plugin-vue breaks HMR when used with vite-plugin-ssr Aug 12, 2022
@brillout
Copy link
Contributor Author

I updated the ticket to reflect the latest findings.

So it seems like a @vitejs/plugin-vue problem.

I think it's probably best if someone familiar with the Vue plugin has a look at this.

@sapphi-red
Copy link
Member

Yeah it seems plugin-vue is failing to find the correct main module as @Demivan said #9341 (comment).
(Changing that line to the code below worked)

  const mainModule = modules.find(
    (m) => (!/type=/.test(m.url) || /type=script/.test(m.url)) && !m.url.includes('extractExportNames')
  )

I think there's two ways to fix this but I'm not sure if either of these is a good way.

  1. somehow change this modules.find's callback to obtain the correct main module
    • I'm not sure if this is possible. The main module is normally imported with import foo from './foo.vue' so we could find the one without any queries. But this might break other codes like import foo from './foo.vue?query'.
  2. change this module.find into module.filter
    • I'm not sure if this works.

@patak-dev
Copy link
Member

If we want to be agnostic, we should define that any query param that isn't part of the submodule scheme of plugin-vue defines a new module. This sounds like a feature request to me, and it may not be a bad addition. Do all other framework plugins work in this way?

About extractExportNames in particular, if you have vite-plugin-ssr handleHotUpdate hook before plugin-vue, you could narrow down the affected modules to remove it before it reaches plugin-vue. But if it is affected, and you need to leave it in place you have the same issue.

One problem I see with allowing {name}.vue?customQuery, is that the namespace is shared between vue and others. We have this problem everywhere though with queries, maybe it would have been good to namespace them (vue_type, plugin-ssr-extractExportNames).

I think one way out is to define that plugin-vue will reload every module with custom queries, and the plugin is expected to narrow it down if it wants to avoid the reload (that I imagine is what vite-plugin-ssr is already doing). We could try to do this change in 3.1. About the implementation, we could first filter any module that has an unrecognized plugin-vue query.

@AaronBeaudoin
Copy link

Just pinging this issue to see if there's been any progress in the last 3 weeks.

@brillout
Copy link
Contributor Author

brillout commented Nov 5, 2022

I made a PR solving this: #10794.

@github-actions github-actions bot locked and limited conversation to collaborators Nov 30, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants