diff --git a/packages/playground/vue/Main.vue b/packages/playground/vue/Main.vue
index 37324329d32bef..465c289bc56317 100644
--- a/packages/playground/vue/Main.vue
+++ b/packages/playground/vue/Main.vue
@@ -2,7 +2,9 @@
Vue SFCs
{{ time }}
-
+
+
+
diff --git a/packages/playground/vue/__tests__/vue.spec.ts b/packages/playground/vue/__tests__/vue.spec.ts
index ffc11531df4add..c331d61fa52e8f 100644
--- a/packages/playground/vue/__tests__/vue.spec.ts
+++ b/packages/playground/vue/__tests__/vue.spec.ts
@@ -133,6 +133,11 @@ describe('hmr', () => {
)
await untilUpdated(() => page.textContent('.hmr-inc'), 'count is 100')
})
+
+ test('should re-render when template is emptied', async () => {
+ editFile('Hmr.vue', () => '')
+ await untilUpdated(() => page.innerHTML('.hmr-block'), '')
+ })
})
describe('src imports', () => {
diff --git a/packages/plugin-vue/src/handleHotUpdate.ts b/packages/plugin-vue/src/handleHotUpdate.ts
index 734c6d4a8d604d..3b3ec974d1638c 100644
--- a/packages/plugin-vue/src/handleHotUpdate.ts
+++ b/packages/plugin-vue/src/handleHotUpdate.ts
@@ -144,7 +144,7 @@ export async function handleHotUpdate({
return [...affectedModules].filter(Boolean) as ModuleNode[]
}
-function isEqualBlock(a: SFCBlock | null, b: SFCBlock | null) {
+export function isEqualBlock(a: SFCBlock | null, b: SFCBlock | null) {
if (!a && !b) return true
if (!a || !b) return false
// src imports will trigger their own updates
diff --git a/packages/plugin-vue/src/main.ts b/packages/plugin-vue/src/main.ts
index d1996b087cde06..645a5032046c9f 100644
--- a/packages/plugin-vue/src/main.ts
+++ b/packages/plugin-vue/src/main.ts
@@ -10,7 +10,7 @@ import {
import { PluginContext, TransformPluginContext } from 'rollup'
import { resolveScript } from './script'
import { transformTemplateInMain } from './template'
-import { isOnlyTemplateChanged } from './handleHotUpdate'
+import { isOnlyTemplateChanged, isEqualBlock } from './handleHotUpdate'
import { RawSourceMap, SourceMapConsumer, SourceMapGenerator } from 'source-map'
import { createRollupError } from './utils/error'
@@ -71,11 +71,23 @@ export async function transformMain(
))
}
- const renderReplace = hasTemplateImport
- ? ssr
+ let renderReplace = ''
+ if (hasTemplateImport) {
+ renderReplace = ssr
? `_sfc_main.ssrRender = _sfc_ssrRender`
: `_sfc_main.render = _sfc_render`
- : ''
+ } else {
+ // #2128
+ // User may empty the template but we didn't provide rerender function before
+ if (
+ prevDescriptor &&
+ !isEqualBlock(descriptor.template, prevDescriptor.template)
+ ) {
+ renderReplace = ssr
+ ? `_sfc_main.ssrRender = () => {}`
+ : `_sfc_main.render = () => {}`
+ }
+ }
// styles
const stylesCode = await genStyleCode(descriptor, pluginContext)