Skip to content

Commit 34632b0

Browse files
authored
fix(vue): same src file request same key (#8059)
1 parent 2c80390 commit 34632b0

File tree

8 files changed

+74
-17
lines changed

8 files changed

+74
-17
lines changed

packages/plugin-vue/src/main.ts

+32-11
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ async function genTemplateCode(
227227
ssr: boolean
228228
) {
229229
const template = descriptor.template!
230+
const hasScoped = descriptor.styles.some((style) => style.scoped)
230231

231232
// If the template is not using pre-processor AND is not using external src,
232233
// compile and inline it directly in the main module. When served in vite this
@@ -241,12 +242,22 @@ async function genTemplateCode(
241242
)
242243
} else {
243244
if (template.src) {
244-
await linkSrcToDescriptor(template.src, descriptor, pluginContext)
245+
await linkSrcToDescriptor(
246+
template.src,
247+
descriptor,
248+
pluginContext,
249+
hasScoped
250+
)
245251
}
246252
const src = template.src || descriptor.filename
247-
const srcQuery = template.src ? `&src=${descriptor.id}` : ``
253+
const srcQuery = template.src
254+
? hasScoped
255+
? `&src=${descriptor.id}`
256+
: '&src=true'
257+
: ''
258+
const scopedQuery = hasScoped ? `&scoped=true` : ``
248259
const attrsQuery = attrsToQuery(template.attrs, 'js', true)
249-
const query = `?vue&type=template${srcQuery}${attrsQuery}`
260+
const query = `?vue&type=template${srcQuery}${scopedQuery}${attrsQuery}`
250261
const request = JSON.stringify(src + query)
251262
const renderFnName = ssr ? 'ssrRender' : 'render'
252263
return {
@@ -284,12 +295,12 @@ async function genScriptCode(
284295
map = script.map
285296
} else {
286297
if (script.src) {
287-
await linkSrcToDescriptor(script.src, descriptor, pluginContext)
298+
await linkSrcToDescriptor(script.src, descriptor, pluginContext, false)
288299
}
289300
const src = script.src || descriptor.filename
290301
const langFallback = (script.src && path.extname(src).slice(1)) || 'js'
291302
const attrsQuery = attrsToQuery(script.attrs, langFallback)
292-
const srcQuery = script.src ? `&src=${descriptor.id}` : ``
303+
const srcQuery = script.src ? `&src=true` : ``
293304
const query = `?vue&type=script${srcQuery}${attrsQuery}`
294305
const request = JSON.stringify(src + query)
295306
scriptCode =
@@ -314,13 +325,22 @@ async function genStyleCode(
314325
for (let i = 0; i < descriptor.styles.length; i++) {
315326
const style = descriptor.styles[i]
316327
if (style.src) {
317-
await linkSrcToDescriptor(style.src, descriptor, pluginContext)
328+
await linkSrcToDescriptor(
329+
style.src,
330+
descriptor,
331+
pluginContext,
332+
style.scoped
333+
)
318334
}
319335
const src = style.src || descriptor.filename
320336
// do not include module in default query, since we use it to indicate
321337
// that the module needs to export the modules json
322338
const attrsQuery = attrsToQuery(style.attrs, 'css')
323-
const srcQuery = style.src ? `&src=${descriptor.id}` : ``
339+
const srcQuery = style.src
340+
? style.scoped
341+
? `&src=${descriptor.id}`
342+
: '&src=true'
343+
: ''
324344
const directQuery = asCustomElement ? `&inline` : ``
325345
const query = `?vue&type=style&index=${i}${srcQuery}${directQuery}`
326346
const styleRequest = src + query + attrsQuery
@@ -390,11 +410,11 @@ async function genCustomBlockCode(
390410
for (let index = 0; index < descriptor.customBlocks.length; index++) {
391411
const block = descriptor.customBlocks[index]
392412
if (block.src) {
393-
await linkSrcToDescriptor(block.src, descriptor, pluginContext)
413+
await linkSrcToDescriptor(block.src, descriptor, pluginContext, false)
394414
}
395415
const src = block.src || descriptor.filename
396416
const attrsQuery = attrsToQuery(block.attrs, block.type)
397-
const srcQuery = block.src ? `&src` : ``
417+
const srcQuery = block.src ? `&src=true` : ``
398418
const query = `?vue&type=${block.type}&index=${index}${srcQuery}${attrsQuery}`
399419
const request = JSON.stringify(src + query)
400420
code += `import block${index} from ${request}\n`
@@ -411,13 +431,14 @@ async function genCustomBlockCode(
411431
async function linkSrcToDescriptor(
412432
src: string,
413433
descriptor: SFCDescriptor,
414-
pluginContext: PluginContext
434+
pluginContext: PluginContext,
435+
scoped?: boolean
415436
) {
416437
const srcFile =
417438
(await pluginContext.resolve(src, descriptor.filename))?.id || src
418439
// #1812 if the src points to a dep file, the resolved id may contain a
419440
// version query.
420-
setSrcDescriptor(srcFile.replace(/\?.*$/, ''), descriptor)
441+
setSrcDescriptor(srcFile.replace(/\?.*$/, ''), descriptor, scoped)
421442
}
422443

423444
// these are built-in query parameters so should be ignored

packages/plugin-vue/src/utils/descriptorCache.ts

+16-5
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,22 @@ export function getSrcDescriptor(
6969
filename: string,
7070
query: VueQuery
7171
): SFCDescriptor {
72-
return cache.get(`${filename}?src=${query.src}`)!
72+
if (query.scoped) {
73+
return cache.get(`${filename}?src=${query.src}`)!
74+
}
75+
return cache.get(filename)!
7376
}
7477

75-
export function setSrcDescriptor(filename: string, entry: SFCDescriptor): void {
76-
// if multiple Vue files use the same src file, they will be overwritten
77-
// should use other key
78-
cache.set(`${filename}?src=${entry.id}`, entry)
78+
export function setSrcDescriptor(
79+
filename: string,
80+
entry: SFCDescriptor,
81+
scoped?: boolean
82+
): void {
83+
if (scoped) {
84+
// if multiple Vue files use the same src file, they will be overwritten
85+
// should use other key
86+
cache.set(`${filename}?src=${entry.id}`, entry)
87+
return
88+
}
89+
cache.set(filename, entry)
7990
}

packages/plugin-vue/src/utils/query.ts

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export interface VueQuery {
55
index?: number
66
lang?: string
77
raw?: boolean
8+
scoped?: boolean
89
}
910

1011
export function parseVueRequest(id: string): {
@@ -22,6 +23,9 @@ export function parseVueRequest(id: string): {
2223
if (query.raw != null) {
2324
query.raw = true
2425
}
26+
if (query.scoped != null) {
27+
query.scoped = true
28+
}
2529
return {
2630
filename,
2731
query
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.one {
2+
background: yellow;
3+
}
4+
5+
.two {
6+
border: solid 1px red;
7+
}

playground/vue/src-import/script.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
import { defineComponent } from 'vue'
22
import SrcImportStyle from './srcImportStyle.vue'
33
import SrcImportStyle2 from './srcImportStyle2.vue'
4+
import SrcImportModuleStyle from './srcImportModuleStyle.vue'
5+
import SrcImportModuleStyle2 from './srcImportModuleStyle2.vue'
46

57
export default defineComponent({
68
components: {
79
SrcImportStyle,
8-
SrcImportStyle2
10+
SrcImportStyle2,
11+
SrcImportModuleStyle,
12+
SrcImportModuleStyle2
913
},
1014
setup() {
1115
return {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<template>
2+
<div :class="$style.one">src for import css module</div>
3+
</template>
4+
<style lang="scss" module src="/@/src-import/css.module.css" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<template>
2+
<div :class="$style.two">src for import css module</div>
3+
</template>
4+
<style lang="scss" module src="/@/src-import/css.module.css" />

playground/vue/src-import/template.html

+2
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ <h2>SFC Src Imports</h2>
33
<div class="src-imports-style">This should be tan</div>
44
<SrcImportStyle></SrcImportStyle>
55
<SrcImportStyle2></SrcImportStyle2>
6+
<SrcImportModuleStyle></SrcImportModuleStyle>
7+
<SrcImportModuleStyle2></SrcImportModuleStyle2>

0 commit comments

Comments
 (0)