Skip to content

Commit 1012367

Browse files
authored
fix: hmr doesn't work when modifying the code of jsx in sfc (#4563)
1 parent 0f1d6be commit 1012367

File tree

9 files changed

+73
-4
lines changed

9 files changed

+73
-4
lines changed
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<script lang="jsx">
2+
import { defineComponent, ref } from 'vue'
3+
4+
export default defineComponent(() => {
5+
const count = ref(4)
6+
const inc = () => count.value++
7+
8+
return () => (
9+
<button class="script" onClick={inc}>
10+
script {count.value}
11+
</button>
12+
)
13+
})
14+
</script>
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { defineComponent, ref } from 'vue'
2+
3+
export default defineComponent(() => {
4+
const count = ref(5)
5+
const inc = () => count.value++
6+
7+
return () => (
8+
<button class="src-import" onClick={inc}>
9+
src import {count.value}
10+
</button>
11+
)
12+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<script src="./SrcImport.jsx"></script>

packages/playground/vue-jsx/__tests__/vue-jsx.spec.ts

+28
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ test('should render', async () => {
55
expect(await page.textContent('.named-specifier')).toMatch('1')
66
expect(await page.textContent('.default')).toMatch('2')
77
expect(await page.textContent('.default-tsx')).toMatch('3')
8+
expect(await page.textContent('.script')).toMatch('4')
9+
expect(await page.textContent('.src-import')).toMatch('5')
810
expect(await page.textContent('.other-ext')).toMatch('Other Ext')
911
})
1012

@@ -17,6 +19,10 @@ test('should update', async () => {
1719
expect(await page.textContent('.default')).toMatch('3')
1820
await page.click('.default-tsx')
1921
expect(await page.textContent('.default-tsx')).toMatch('4')
22+
await page.click('.script')
23+
expect(await page.textContent('.script')).toMatch('5')
24+
await page.click('.src-import')
25+
expect(await page.textContent('.src-import')).toMatch('6')
2026
})
2127

2228
if (!isBuild) {
@@ -74,4 +80,26 @@ if (!isBuild) {
7480
// should not affect other components on the page
7581
expect(await page.textContent('.named')).toMatch('1')
7682
})
83+
84+
test('hmr: script in .vue', async () => {
85+
editFile('Script.vue', (code) =>
86+
code.replace('script {count', 'script updated {count')
87+
)
88+
await untilUpdated(() => page.textContent('.script'), 'script updated 4')
89+
90+
expect(await page.textContent('.src-import')).toMatch('6')
91+
})
92+
93+
test('hmr: src import in .vue', async () => {
94+
await page.click('.script')
95+
editFile('SrcImport.jsx', (code) =>
96+
code.replace('src import {count', 'src import updated {count')
97+
)
98+
await untilUpdated(
99+
() => page.textContent('.src-import'),
100+
'src import updated 5'
101+
)
102+
103+
expect(await page.textContent('.script')).toMatch('5')
104+
})
77105
}

packages/playground/vue-jsx/main.jsx

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { createApp } from 'vue'
22
import { Named, NamedSpec, default as Default } from './Comps'
33
import { default as TsxDefault } from './Comp'
44
import OtherExt from './OtherExt.tesx'
5+
import JsxScript from './Script.vue'
6+
import JsxSrcImport from './SrcImport.vue'
57

68
function App() {
79
return (
@@ -11,6 +13,8 @@ function App() {
1113
<Default />
1214
<TsxDefault />
1315
<OtherExt />
16+
<JsxScript />
17+
<JsxSrcImport />
1418
</>
1519
)
1620
}

packages/playground/vue-jsx/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"serve": "vite preview"
1010
},
1111
"devDependencies": {
12-
"@vitejs/plugin-vue-jsx": "^1.0.0"
12+
"@vitejs/plugin-vue-jsx": "^1.0.0",
13+
"@vitejs/plugin-vue": "^1.3.0"
1314
}
1415
}

packages/playground/vue-jsx/vite.config.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const vueJsxPlugin = require('@vitejs/plugin-vue-jsx')
2+
const vuePlugin = require('@vitejs/plugin-vue')
23

34
/**
45
* @type {import('vite').UserConfig}
@@ -7,7 +8,8 @@ module.exports = {
78
plugins: [
89
vueJsxPlugin({
910
include: [/\.tesx$/, /\.[jt]sx$/]
10-
})
11+
}),
12+
vuePlugin()
1113
],
1214
build: {
1315
// to make tests faster

packages/plugin-vue-jsx/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ function vueJsxPlugin(options = {}) {
207207
) + `\nexport default __default__`
208208
}
209209

210-
if (needHmr && !ssr) {
210+
if (needHmr && !ssr && !/\?vue&type=script/.test(id)) {
211211
let code = result.code
212212
let callbackCode = ``
213213
for (const { local, exported, id } of hotComponents) {

packages/plugin-vue/src/handleHotUpdate.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,14 @@ export async function handleHotUpdate({
4646
!isEqualBlock(descriptor.script, prevDescriptor.script) ||
4747
!isEqualBlock(descriptor.scriptSetup, prevDescriptor.scriptSetup)
4848
) {
49-
affectedModules.add(mainModule)
49+
let scriptModule: ModuleNode | undefined
50+
if (descriptor.script?.lang && !descriptor.script.src) {
51+
const scriptModuleRE = new RegExp(
52+
`type=script.*&lang\.${descriptor.script.lang}$`
53+
)
54+
scriptModule = modules.find((m) => scriptModuleRE.test(m.url))
55+
}
56+
affectedModules.add(scriptModule || mainModule)
5057
}
5158

5259
if (!isEqualBlock(descriptor.template, prevDescriptor.template)) {

0 commit comments

Comments
 (0)