Skip to content

Commit 709e4b0

Browse files
committed
fix(plugin-vue): fix hmr issue in vuejs/core#4358
1 parent ecafa80 commit 709e4b0

File tree

4 files changed

+32
-7
lines changed

4 files changed

+32
-7
lines changed

packages/playground/vue/Hmr.vue

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
<script setup lang="ts">
88
import { ref } from 'vue'
9+
import Node from './Node.vue'
910
1011
let foo: number = 0
1112

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

+7
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,13 @@ describe('hmr', () => {
157157
await untilUpdated(() => page.textContent('.hmr-inc'), 'count is 100')
158158
})
159159

160+
test('global hmr for some scenarios', async () => {
161+
editFile('Hmr.vue', (code) =>
162+
code.replace('</template>', ' <Node/>\n' + '</template>')
163+
)
164+
await untilUpdated(() => page.innerHTML('.node'), 'this is node')
165+
})
166+
160167
test('should re-render when template is emptied', async () => {
161168
editFile('Hmr.vue', () => '')
162169
await untilUpdated(() => page.innerHTML('.hmr-block'), '<!---->')

packages/plugin-vue/src/handleHotUpdate.ts

+24-6
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,7 @@ export async function handleHotUpdate(
3838
)
3939
const templateModule = modules.find((m) => /type=template/.test(m.url))
4040

41-
if (
42-
!isEqualBlock(descriptor.script, prevDescriptor.script) ||
43-
!isEqualBlock(descriptor.scriptSetup, prevDescriptor.scriptSetup)
44-
) {
41+
if (hasScriptChanged(prevDescriptor, descriptor)) {
4542
let scriptModule: ModuleNode | undefined
4643
if (descriptor.script?.lang && !descriptor.script.src) {
4744
const scriptModuleRE = new RegExp(
@@ -174,11 +171,32 @@ export function isOnlyTemplateChanged(
174171
next: SFCDescriptor
175172
): boolean {
176173
return (
177-
isEqualBlock(prev.script, next.script) &&
178-
isEqualBlock(prev.scriptSetup, next.scriptSetup) &&
174+
!hasScriptChanged(prev, next) &&
179175
prev.styles.length === next.styles.length &&
180176
prev.styles.every((s, i) => isEqualBlock(s, next.styles[i])) &&
181177
prev.customBlocks.length === next.customBlocks.length &&
182178
prev.customBlocks.every((s, i) => isEqualBlock(s, next.customBlocks[i]))
183179
)
184180
}
181+
182+
function hasScriptChanged(prev: SFCDescriptor, next: SFCDescriptor): boolean {
183+
if (!isEqualBlock(prev.script, next.script)) {
184+
return true
185+
}
186+
if (!isEqualBlock(prev.scriptSetup, next.scriptSetup)) {
187+
return true
188+
}
189+
190+
// vue core #3176
191+
// <script setup lang="ts"> prunes non-unused imports
192+
// the imports pruning depends on template, so script may need to re-compile
193+
// based on template changes
194+
const prevResolvedScript = getResolvedScript(prev, false)
195+
// this is only available in vue@^3.2.23
196+
const prevImports = prevResolvedScript?.imports
197+
if (prevImports) {
198+
return next.shouldForceReload(prevImports)
199+
}
200+
201+
return false
202+
}

packages/plugin-vue/src/script.ts

-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ export function resolveScript(
5656
inlineTemplate: isUseInlineTemplate(descriptor, !options.devServer),
5757
refTransform: options.refTransform !== false,
5858
templateOptions: resolveTemplateCompilerOptions(descriptor, options, ssr),
59-
// @ts-ignore TODO remove ignore when we support this in @vue/compiler-sfc
6059
sourceMap: options.sourceMap
6160
})
6261

0 commit comments

Comments
 (0)