Skip to content

Commit

Permalink
fix(hmr): should reload if relies file changed after re-render (#471)
Browse files Browse the repository at this point in the history
  • Loading branch information
edison1105 authored Nov 11, 2024
1 parent de2f6b3 commit 62b17f3
Showing 5 changed files with 36 additions and 2 deletions.
8 changes: 7 additions & 1 deletion packages/plugin-vue/src/index.ts
Original file line number Diff line number Diff line change
@@ -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<Api> {
},

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)
}
13 changes: 12 additions & 1 deletion packages/plugin-vue/src/main.ts
Original file line number Diff line number Diff line change
@@ -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 => {`,
3 changes: 3 additions & 0 deletions playground/vue/Hmr.vue
Original file line number Diff line number Diff line change
@@ -2,11 +2,14 @@
<h2 class="hmr">HMR</h2>
<p>Click the button then edit this message. The count should be preserved.</p>
<button class="hmr-inc" @click="count++">count is {{ count }}</button>
<span class="hmr-number">{{ number }}</span>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import Node from './Node.vue'
import { test } from './lib.js'
const number = test()
let foo: number = 0
11 changes: 11 additions & 0 deletions playground/vue/__tests__/vue.spec.ts
Original file line number Diff line number Diff line change
@@ -206,6 +206,17 @@ describe('hmr', () => {
await untilUpdated(() => page.textContent('.hmr-inc'), 'count is 100')
})

test('should reload when relies file changed', async () => {
// rerender
editFile('Hmr.vue', (code) => code.replace('HMR', 'HMR updated'))
await untilUpdated(() => page.textContent('h2.hmr'), 'HMR updated')
await untilUpdated(() => page.textContent('.hmr-number'), '100')

// reload
editFile('lib.js', (code) => code.replace('100', '200'))
await untilUpdated(() => page.textContent('.hmr-number'), '200')
})

test('global hmr for some scenarios', async () => {
editFile('Hmr.vue', (code) =>
code.replace('</template>', ' <Node/>\n' + '</template>'),
3 changes: 3 additions & 0 deletions playground/vue/lib.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function test() {
return 100
}

0 comments on commit 62b17f3

Please sign in to comment.