@@ -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 ) => ! / t y p e = / . test ( m . id ) || / t y p e = s c r i p t / . test ( m . id )
43- )
44- }
37+ const filteredModules = new Set ( )
38+ const mainModule = modules . find (
39+ ( m ) => ! / t y p e = / . test ( m . id ) || / t y p e = s c r i p t / . test ( m . id )
40+ )
41+ const templateModule = modules . find ( ( m ) => / t y p e = t e m p l a t e / . 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 ) => / t y p e = t e m p l a t e / . 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