Skip to content
This repository was archived by the owner on Jan 18, 2022. It is now read-only.

Commit 59d1c25

Browse files
committed
wip: refactor hmr handling
1 parent 29bbe7a commit 59d1c25

File tree

1 file changed

+39
-23
lines changed

1 file changed

+39
-23
lines changed

src/handleHotUpdate.ts

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,17 @@ export async function handleHotUpdate(file: string, modules: any[]) {
3434
setDescriptor(file, descriptor)
3535

3636
let needRerender = false
37-
const filteredModules = []
38-
39-
const reload = () => {
40-
debug(`[vue:reload] ${file}`)
41-
return modules.filter(
42-
(m) => !/type=/.test(m.id) || /type=script/.test(m.id)
43-
)
44-
}
37+
const filteredModules = new Set()
38+
const mainModule = modules.find(
39+
(m) => !/type=/.test(m.id) || /type=script/.test(m.id)
40+
)
41+
const templateModule = modules.find((m) => /type=template/.test(m.id))
4542

4643
if (
4744
!isEqualBlock(descriptor.script, prevDescriptor.script) ||
4845
!isEqualBlock(descriptor.scriptSetup, prevDescriptor.scriptSetup)
4946
) {
50-
return reload()
47+
filteredModules.add(mainModule)
5148
}
5249

5350
if (!isEqualBlock(descriptor.template, prevDescriptor.template)) {
@@ -56,7 +53,7 @@ export async function handleHotUpdate(file: string, modules: any[]) {
5653
// metadata will not be available since the script part isn't loaded.
5754
// in this case, reuse the compiled script from previous descriptor.
5855
setResolvedScript(descriptor, getResolvedScript(prevDescriptor)!)
59-
needRerender = true
56+
filteredModules.add(templateModule)
6057
}
6158

6259
let didUpdateStyle = false
@@ -66,13 +63,15 @@ export async function handleHotUpdate(file: string, modules: any[]) {
6663
// force reload if CSS vars injection changed
6764
if (descriptor.cssVars) {
6865
if (prevDescriptor.cssVars.join('') !== descriptor.cssVars.join('')) {
69-
return reload()
66+
filteredModules.add(mainModule)
7067
}
7168
}
7269

7370
// force reload if scoped status has changed
7471
if (prevStyles.some((s) => s.scoped) !== nextStyles.some((s) => s.scoped)) {
75-
return reload()
72+
// template needs to be invalidated as well
73+
filteredModules.add(templateModule)
74+
filteredModules.add(mainModule)
7675
}
7776

7877
// only need to update styles if not reloading, since reload forces
@@ -82,25 +81,42 @@ export async function handleHotUpdate(file: string, modules: any[]) {
8281
const next = nextStyles[i]
8382
if (!prev || !isEqualBlock(prev, next)) {
8483
didUpdateStyle = true
85-
filteredModules.push(modules.find((m) => m.id.includes(`index=${i}`)))
84+
const mod = modules.find((m) => m.id.includes(`type=style&index=${i}`))
85+
if (mod) {
86+
filteredModules.add(mod)
87+
} else {
88+
// new style block - force reload
89+
filteredModules.add(mainModule)
90+
}
8691
}
8792
}
93+
if (prevStyles.length > nextStyles.length) {
94+
// style block removed - force reload
95+
filteredModules.add(mainModule)
96+
}
8897

8998
const prevCustoms = prevDescriptor.customBlocks || []
9099
const nextCustoms = descriptor.customBlocks || []
91100

92101
// custom blocks update causes a reload
93102
// because the custom block contents is changed and it may be used in JS.
94-
if (
95-
nextCustoms.some(
96-
(_, i) => !prevCustoms[i] || !isEqualBlock(prevCustoms[i], nextCustoms[i])
97-
)
98-
) {
99-
return reload()
103+
for (let i = 0; i < nextCustoms.length; i++) {
104+
const prev = prevCustoms[i]
105+
const next = nextCustoms[i]
106+
if (!prev || !isEqualBlock(prev, next)) {
107+
const mod = modules.find((m) =>
108+
m.id.includes(`type=${prev.type}&index=${i}`)
109+
)
110+
if (mod) {
111+
filteredModules.add(mod)
112+
} else {
113+
filteredModules.add(mainModule)
114+
}
115+
}
100116
}
101-
102-
if (needRerender) {
103-
filteredModules.push(modules.find((m) => /type=template/.test(m.id)))
117+
if (prevCustoms.length > nextCustoms.length) {
118+
// block rmeoved, force reload
119+
filteredModules.add(mainModule)
104120
}
105121

106122
let updateType = []
@@ -113,7 +129,7 @@ export async function handleHotUpdate(file: string, modules: any[]) {
113129
if (updateType.length) {
114130
debug(`[vue:update(${updateType.join('&')})] ${file}`)
115131
}
116-
return filteredModules
132+
return [...filteredModules].filter(Boolean)
117133
}
118134

119135
// vitejs/vite#610 when hot-reloading Vue files, we read immediately on file

0 commit comments

Comments
 (0)