vite
vite copied to clipboard
[Vite 3] `@vitejs/plugin-vue` breaks HMR when used with `vite-plugin-ssr`
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
- [X] Follow our Code of Conduct
- [X] Read the Contributing Guidelines.
- [X] Read the docs.
- [X] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- [X] Make sure this is a Vite issue and not a framework-specific issue. For example, if it's a Vue SFC related bug, it should likely be reported to vuejs/core instead.
- [X] Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
- [X] The provided reproduction is a minimal reproducible example of the bug.
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.
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.
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.
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
:
https://github.com/vitejs/vite/blob/364aae13f0826169e8b1c5db41ac6b5bb2756958/packages/plugin-vue/src/handleHotUpdate.ts#L36-L38
We can either change vite detection of main module or add type={something}
to vite-plugin-ssr
module ids
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
?
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.
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.
Yeah it seems plugin-vue is failing to find the correct main module as @Demivan said https://github.com/vitejs/vite/issues/9341#issuecomment-1199914922. (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.
- 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 likeimport foo from './foo.vue?query'
.
- I'm not sure if this is possible. The main module is normally imported with
- change this
module.find
intomodule.filter
- I'm not sure if this works.
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.
Just pinging this issue to see if there's been any progress in the last 3 weeks.
I made a PR solving this: https://github.com/vitejs/vite/pull/10794.