From 62b17f3eaf839a9bdaadde5c24e84e4dbf04bbfc Mon Sep 17 00:00:00 2001 From: edison Date: Mon, 11 Nov 2024 09:10:21 +0800 Subject: [PATCH] fix(hmr): should reload if relies file changed after re-render (#471) --- packages/plugin-vue/src/index.ts | 8 +++++++- packages/plugin-vue/src/main.ts | 13 ++++++++++++- playground/vue/Hmr.vue | 3 +++ playground/vue/__tests__/vue.spec.ts | 11 +++++++++++ playground/vue/lib.js | 3 +++ 5 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 playground/vue/lib.js diff --git a/packages/plugin-vue/src/index.ts b/packages/plugin-vue/src/index.ts index 3d547040..c11a8efd 100644 --- a/packages/plugin-vue/src/index.ts +++ b/packages/plugin-vue/src/index.ts @@ -1,6 +1,6 @@ import fs from 'node:fs' import type { Plugin, ViteDevServer } from 'vite' -import { createFilter } from 'vite' +import { createFilter, normalizePath } from 'vite' /* eslint-disable import/no-duplicates */ import type { SFCBlock, @@ -200,6 +200,12 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin { }, handleHotUpdate(ctx) { + ctx.server.ws.send({ + type: 'custom', + event: 'file-changed', + data: { file: normalizePath(ctx.file) }, + }) + if (options.value.compiler.invalidateTypeCache) { options.value.compiler.invalidateTypeCache(ctx.file) } diff --git a/packages/plugin-vue/src/main.ts b/packages/plugin-vue/src/main.ts index fce8c8ea..eddcfff3 100644 --- a/packages/plugin-vue/src/main.ts +++ b/packages/plugin-vue/src/main.ts @@ -148,9 +148,20 @@ export async function transformMain( `typeof __VUE_HMR_RUNTIME__ !== 'undefined' && ` + `__VUE_HMR_RUNTIME__.createRecord(_sfc_main.__hmrId, _sfc_main)`, ) + output.push( + `import.meta.hot.on('file-changed', ({ file }) => {`, + ` __VUE_HMR_RUNTIME__.CHANGED_FILE = file`, + `})`, + ) // check if the template is the only thing that changed if (prevDescriptor && isOnlyTemplateChanged(prevDescriptor, descriptor)) { - output.push(`export const _rerender_only = true`) + // #7 only consider re-render if the HMR is triggered by the current component, + // otherwise reload. Due to vite will cache the transform result. If the HMR + // is triggered by other files that the current component relies on, a reload + // is required. + output.push( + `export const _rerender_only = __VUE_HMR_RUNTIME__.CHANGED_FILE === ${JSON.stringify(normalizePath(filename))}`, + ) } output.push( `import.meta.hot.accept(mod => {`, diff --git a/playground/vue/Hmr.vue b/playground/vue/Hmr.vue index 5535467a..541929d4 100644 --- a/playground/vue/Hmr.vue +++ b/playground/vue/Hmr.vue @@ -2,11 +2,14 @@

HMR

Click the button then edit this message. The count should be preserved.

+ {{ number }}