vite
vite copied to clipboard
Component Framework global components are not correctly loaded when using pug + scoped style
Describe the bug
With Quasar I'm using the @quasar/vite-plugin v1.1.1
and the plugin property autoImportComponentCase: 'pascal'
When using this in combination with a template lang=pug
and style scoped
I get warnings and a blank white page with no rendered content.
At Quasar Land (Discord) we (@yusufkandemir, @patak-dev and me) already found out that there is a new incompatibility coming from @vitejs/plugin-vue >= v3
and that the template also gets applied a scoped query param where as when not using pug it does not.
https://discord.com/channels/415874313728688138/902518756436226079/1002122942852902964
https://discord.com/channels/415874313728688138/902518756436226079/1002127704138715176
Current workaround:
Using a css class named like the component and use that instead of scoped
keyword.
Reproduction
https://stackblitz.com/edit/vitejs-vite-llrb6t?file=src%2FApp.vue,package.json,src%2Fmain.ts,vite.config.ts&terminal=dev
System Info
System:
OS: macOS 12.4
CPU: (10) arm64 Apple M1 Max
Memory: 4.91 GB / 32.00 GB
Shell: 5.8.1 - /bin/zsh
Binaries:
Node: 18.4.0 - ~/.nvm/versions/node/v18.4.0/bin/node
npm: 8.12.1 - ~/.nvm/versions/node/v18.4.0/bin/npm
Browsers:
Chrome: 103.0.5060.134
Safari: 15.5
npmPackages:
@vitejs/plugin-vue: ~3.0.1 => 3.0.1
vite: ~3.0.3 => 3.0.3
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.
The value of the autoImportComponentCase
doesn't affect the behavior. (as long as you match it in your code of course)
Also, let me move over my text from Discord to here so that it's more readable and copyable.
If you use scoped css but not pug, it still works.
For some reason, when you pug and scoped css at the same time, the template also gets
&scoped=...
in the resource URL. And, the regex targeting the template can't match it, so the auto-loading gets disabled on that template.HTML + Regular SCSS: template:
http://localhost:5173/src/App.vue
style:http://localhost:5173/src/App.vue?vue&type=style&index=0&lang.scss
HTML + Scoped SCSS: template:
http://localhost:5173/src/App.vue
style:http://localhost:5173/src/App.vue?vue&type=style&index=0&scoped=7a7a37b1&lang.scss
Pug + Regular SCSS: template:
http://localhost:5173/src/App.vue?vue&type=template&lang.js
style:http://localhost:5173/src/App.vue?vue&type=style&index=0&lang.scss
Pug + Scoped SCSS: template:
http://localhost:5173/src/App.vue?vue&type=template&scoped=7a7a37b1&lang.js
style:http://localhost:5173/src/App.vue?vue&type=style&index=0&scoped=7a7a37b1&lang.scss
The solution is to update to regex to allow it, but the question is whether this behavior of Vite is intended or not.
https://github.com/quasarframework/quasar/blob/bb44635a8e97210937eb3539968a6b6aa37ae778/vite-plugin/src/vue-transform.js#L6
export const vueTransformRegex = /\.vue(?:\?vue&type=(?:template|script)(?:&setup=true)?&lang\.(?:j|t)s)?$/
When using Pug + Scopes SCSS, if it's intended for the template resource query to also get
scoped
, I'll update the regex above to allow it. Do you know if it's intended?Also, by any chance, do you know if there is a more future-proof solution than just doing this in our Vite plugin:
transform (src, id) { if (vueTransformRegex.test(id) === true) { return { code: vueTransform(src, opts.autoImportComponentCase), map: null // provide source map if available } } else if // ...
or perhaps loosen up the regex, or have a better way of following the changes on this kind of stuff? Any input is welcome!
the question is whether this behavior of Vite is intended or not.
This is intended. When lang
or src
attribute is not defined on <template>
, it is inlined in the main request. So the URL ends with .vue
.
https://github.com/vitejs/vite/blob/cd69358177dd3d93bc19084ad0ee09f6b85c047c/packages/plugin-vue/src/main.ts#L253-L255
When using pug, it is not inlined and scope=$id
was added for build --watch
(https://github.com/vitejs/vite/pull/7989).
When the template is inlined in the main request, this is not needed. So pug one includes scoped=7a7a37b1
but html one does not include it.
do you know if there is a more future-proof solution than just doing this in our Vite plugin
I think doing something similar to this would be more future-proof. https://github.com/vitejs/vite/blob/cd69358177dd3d93bc19084ad0ee09f6b85c047c/packages/plugin-vue/src/index.ts#L180-L197
const f = id => {
if (id.endsWith('.vue')) return true
const { query } = parseVueRequest(id)
return (
query.vue &&
(query.type === 'script' || query.type === 'template')) &&
('lang.ts' in query || 'lang.js' in query)
)
}
@sapphi-red I wonder if plugin-vue should export some utilities to handle these cases. It could be easier to change internals later